Example #1
0
/* pt_regs defined in include/asm-x86/ptrace.h
 * *
 * * For information associating registers with function arguments, see:
 * * arch/x86/kernel/entry_64.S
 * */
static int intercept(struct kprobe *kp, struct pt_regs *regs)
{
    int ret = 0;
    int mlength = regs->dx;
    char *message = kmalloc(sizeof(void*)*(mlength+1), GFP_KERNEL);
    char *name;
    int i;
    node* n;
    
    //Get time of day
    struct timeval t;
    do_gettimeofday(&t);

    switch (regs->ax) {
      case __NR_mq_open:
	    name = kmalloc(sizeof(void*) * (strnlen_user((char *)regs->di, 255)), GFP_KERNEL);
	    if(copy_from_user(name, (char *)regs->di, strnlen_user((char *)regs->di, 255))){
		return -EFAULT;
	    }
	    n = create_node(regs->ax, current->pid, current->tgid, (int)t.tv_sec, name, 0, NULL); 
	    enqueue(n);

	    kfree(name);
      break;

      case __NR_mq_timedsend:
      case __NR_mq_timedreceive:
          /*determine if message is a string by checking if each byte
          *is a printable character, and that the last byte is null
          *
          */
	  if (copy_from_user(message, (char *)regs->si, mlength)){
		return -EFAULT;
	  }
	  printk("%s\n",message);
	  for(i = 0; i < mlength; i++){
		if(i < mlength){
			if(*(message + i) < 32 || *(message + i) > 127){
				strcpy(message, "(bin)");
				break; 
			}
		}else{
			if(*(message + i) != '\0'){
				strcpy(message, "(bin)");
			}
		}
	  }
	    n = create_node(regs->ax, current->pid, current->tgid, (int)t.tv_sec, NULL, mlength, message); 
	    enqueue(n);

	    kfree(message);
      break;

      default:
          ret = -1;
          break;
    }
    return ret;
}
Example #2
0
int
dm_path_to_fshdl(
	char		*path,		/* any path name */
	void		*hanp,		/* user's data buffer */
	size_t		*hlenp)		/* set to size of data copied */
{
	/* REFERENCED */
	dm_fsreg_t	*fsrp;
	xfs_handle_t	handle;
	vnode_t		*vp;
	size_t		hlen;
	int		error;
	int		lc;		/* lock cookie */
	struct nameidata nd;
	struct inode *inode;
	size_t		len;
	char		*name;

	/* XXX get things straightened out so getname() works here? */
	len = strnlen_user(path, 2000);
	name = kmem_alloc(len, KM_SLEEP);
	if (copy_from_user(name, path, len))
		return(EFAULT);

	error = 0;
	if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd))
		error = path_walk(name, &nd);
	if (error)
		return error;
	kmem_free(name, len);

	ASSERT(nd.dentry);
	ASSERT(nd.dentry->d_inode);

	inode = igrab(nd.dentry->d_inode);
	path_release(&nd);

	/* we need the vnode */
	vp = LINVFS_GET_VP(inode);
	if (!vp || !vp->v_vfsp->vfs_altfsid) {
		/* we're not in XFS anymore, Toto */
		iput(inode);
		return EINVAL;
	}

	error = dm_vp_to_handle(vp, &handle);
	iput(inode);/*was VN_RELE(vp);*/

	if (error)
		return(error);

	if ((fsrp = dm_find_fsreg_and_lock((fsid_t*)&handle.ha_fsid, &lc)) == NULL)
		return(EBADF);
	mutex_spinunlock(&fsrp->fr_lock, lc);

	hlen = FSHSIZE;
	if(copy_to_user(hanp, &handle, (int)hlen))
		return(EFAULT);
	return(put_user(hlen,hlenp));
}
Example #3
0
char *strndup_user(const char __user *s, long n)
{
	char *p;
	long length;

	length = strnlen_user(s, n);

	if (!length)
		return ERR_PTR(-EFAULT);

	if (length > n)
		return ERR_PTR(-EINVAL);

	p = kmalloc(length, GFP_KERNEL);

	if (!p)
		return ERR_PTR(-ENOMEM);

	if (copy_from_user(p, s, length)) {
		kfree(p);
		return ERR_PTR(-EFAULT);
	}

	p[length - 1] = '\0';

	return p;
}
Example #4
0
static int
u_get_name(char **name, const char *u_name)
{
	/* Valid for PPC, but why is strnlen_user() defined differently from 
	   the strnlen() library call?  This one includes the \0 at the end. */

	int len = strnlen_user(u_name, DPM_NAME_SIZE);
	int ret;

	if (len > DPM_NAME_SIZE) {
		trace("Name too long\n");
		return -EINVAL;
	}
	if (!(*name = (char *) kmalloc(len, GFP_KERNEL))) {
		trace("No memory\n");
		return -ENOMEM;
	}
	if (copy_from_user(*name, u_name, len)) {
		trace("u_get_name fault\n");
		ret = -EFAULT;
		goto free_name;
	}
	if (check_name(*name)) {
		trace("name doesn't check out\n");
		ret = EINVAL;
		goto free_name;
	}
	return 0;
free_name:
	free_name(*name);
	return ret;
}
Example #5
0
ssize_t device_write( struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	printk("device write %d byte\n",count);	
	if(copy_from_user(my_buffer,buf,count)) return -1;
	printk("%s--%ld\n",my_buffer,strnlen_user(buf,255));
	return 1;
}
Example #6
0
int user_register_module (user_req_t *u_info)
{
	int idx, len, ret;
	tcapi_template_t *tcapi;
	char modulename [MAX_URI_LEN+1];

	ret = check_module_version(u_info);
	if (ret)
		return ret;

	/*
	 * Check module name length.
	 */
	ret = strnlen_user(u_info->objectname, MAX_URI_LEN+2);
	if (ret < 0)
		goto out;
	ret = -EINVAL;
	if (ret >= MAX_URI_LEN)
		goto out;

	Dprintk("register user-module, %p.\n", u_info);
	ret = strncpy_from_user(modulename, u_info->objectname, MAX_URI_LEN);
	if (ret < 0)
		goto out;
	modulename[ret] = 0;
	Dprintk("... user-module is: {%s}.\n", modulename);
	len = strlen(modulename);
	if (!len)
		printk(KERN_ERR "no module name provided: please upgrade your TUX user-space utilities!\n");
	if (!len || (len > MAX_URI_LEN))
		return -EINVAL;
	Dprintk("... user-module len is: %d.\n", len);

	ret = copy_from_user(&idx, &u_info->module_index, sizeof(int));
	if (ret || !idx)
		goto out;
	Dprintk("... user-module index is: %d.\n", idx);

	ret = -ENOMEM;
	tcapi = (tcapi_template_t *) kmalloc(sizeof(*tcapi), GFP_KERNEL);
	if (!tcapi)
		goto out;
	memset(tcapi, 0, sizeof(*tcapi));

	tcapi->vfs_name = (char *) kmalloc(len+1, GFP_KERNEL);
	if (!tcapi->vfs_name) {
		kfree(tcapi);
		goto out;
	}
	strcpy(tcapi->vfs_name, modulename);
	tcapi->userspace_id = idx;

	Dprintk("... registering module {%s}.\n", tcapi->vfs_name);
	ret = register_tuxmodule(tcapi);
out:
	return ret;
}
Example #7
0
static char *
repl_strndup_user(const char __user *s, long n)
{
    char *ret_val;
    ret_val = strndup_user(s, n);
    
    if (!IS_ERR(ret_val))
        klc_add_alloc((void *)ret_val, strnlen_user(s, n), stack_depth);
    
    return ret_val;
}
void
gr_handle_exec_args(struct linux_binprm *bprm, struct user_arg_ptr argv)
{
#ifdef CONFIG_GRKERNSEC_EXECLOG
	char *grarg = gr_exec_arg_buf;
	unsigned int i, x, execlen = 0;
	char c;

	if (!((grsec_enable_execlog && grsec_enable_group &&
	       in_group_p(grsec_audit_gid))
	      || (grsec_enable_execlog && !grsec_enable_group)))
		return;

	mutex_lock(&gr_exec_arg_mutex);
	memset(grarg, 0, sizeof(gr_exec_arg_buf));

	for (i = 0; i < bprm->argc && execlen < 128; i++) {
		const char __user *p;
		unsigned int len;

		p = get_user_arg_ptr(argv, i);
		if (IS_ERR(p))
			goto log;

		len = strnlen_user(p, 128 - execlen);
		if (len > 128 - execlen)
			len = 128 - execlen;
		else if (len > 0)
			len--;
		if (copy_from_user(grarg + execlen, p, len))
			goto log;

		/* rewrite unprintable characters */
		for (x = 0; x < len; x++) {
			c = *(grarg + execlen + x);
			if (c < 32 || c > 126)
				*(grarg + execlen + x) = ' ';
		}

		execlen += len;
		*(grarg + execlen) = ' ';
		*(grarg + execlen + 1) = '\0';
		execlen++;
	}

      log:
	gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_path.dentry,
			bprm->file->f_path.mnt, grarg);
	mutex_unlock(&gr_exec_arg_mutex);
#endif
	return;
}
Example #9
0
/**
 * Get the size of a string specified by linear address.
 * @proc  process address
 * @s  The string to measure (linear address).
 * @maxlen  The maximum valid length
 *
 * Get the size of a NUL-terminated string.
 *
 * Returns the size of the string _including_ the terminating NULL.
 * On kernel exception, returns 0.
 * If the string is too long, returns a value greater than @maxlen.
 */
long do_strnlen(kipc_msg_t *m_ptr)
{
	int proc_nr;
	struct proc *p;

	if (!m_ptr->STRNLEN_STR || !isokendpt(m_ptr->STRNLEN_PROC_E, &proc_nr) ||
	    m_ptr->STRNLEN_MAXLEN <= 0)
		return -EINVAL;

	p = proc_addr(proc_nr);

	return strnlen_user(p, m_ptr->STRNLEN_STR, m_ptr->STRNLEN_MAXLEN);
}
Example #10
0
long strncpy_from_user(char *__to, const char __user *__from, long __len)
{
	int l = strnlen_user(__from, __len);
	int is_zt = 1;

	if (l > __len) {
		is_zt = 0;
		l = __len;
	}

	if (l == 0 || copy_from_user(__to, __from, l))
		return -EFAULT;

	if (is_zt)
		l--;
	return l;
}
Example #11
0
/*
 * strndup_user - duplicate an existing string from user space
 * @s: The string to duplicate
 * @n: Maximum number of bytes to copy, including the trailing NUL.
 */
char *strndup_user(const char __user *s, long n)
{
	char *p;
	long length;

	length = strnlen_user(s, n);

	if (!length)
		return ERR_PTR(-EFAULT);

	if (length > n)
		return ERR_PTR(-EINVAL);

	p = memdup_user(s, length);

	if (IS_ERR(p))
		return p;

	p[length - 1] = '\0';

	return p;
}
Example #12
0
int user_unregister_module (user_req_t *u_info)
{
	int len, ret;
	tcapi_template_t *tcapi;
	char modulename [MAX_URI_LEN+1];

	/*
	 * Check module name length.
	 */
	ret = strnlen_user(u_info->objectname, MAX_URI_LEN+2);
	if (ret < 0)
		goto out;
	ret = -EINVAL;
	if (ret >= MAX_URI_LEN)
		goto out;
	Dprintk("unregister user-module, %p.\n", u_info);
	ret = strncpy_from_user(modulename, u_info->objectname, MAX_URI_LEN);
	if (ret <= 0)
		goto out;
	modulename[ret] = 0;
	Dprintk("... user-module is: {%s}.\n", modulename);
	len = strlen(modulename);
	if (!len || (len > MAX_URI_LEN))
		return -EINVAL;
	Dprintk("... user-module len is: %d.\n", len);

	Dprintk("... unregistering module {%s}.\n", modulename);
	tcapi = unregister_tuxmodule(modulename);
	ret = -EINVAL;
	if (tcapi) {
		ret = 0;
		kfree(tcapi->vfs_name);
		kfree(tcapi);
	}
out:
	return ret;
}
Example #13
0
/*
 * join the session keyring
 * - implements keyctl(KEYCTL_JOIN_SESSION_KEYRING)
 */
long keyctl_join_session_keyring(const char __user *_name)
{
	char *name;
	long nlen, ret;

	/* fetch the name from userspace */
	name = NULL;
	if (_name) {
		ret = -EFAULT;
		nlen = strnlen_user(_name, PAGE_SIZE - 1);
		if (nlen <= 0)
			goto error;

		ret = -EINVAL;
		if (nlen > PAGE_SIZE - 1)
			goto error;

		ret = -ENOMEM;
		name = kmalloc(nlen + 1, GFP_KERNEL);
		if (!name)
			goto error;

		ret = -EFAULT;
		if (copy_from_user(name, _name, nlen + 1) != 0)
			goto error2;
	}

	/* join the session */
	ret = join_session_keyring(name);

 error2:
	kfree(name);
 error:
	return ret;

} /* end keyctl_join_session_keyring() */
Example #14
0
long verify_and_copy_args(struct wrapfs_key_info **kargs, struct wrapfs_key_info *args) {
	long rc=0;
	unsigned int key_len;

	/* check whether args is a valid address in user space */
	if(args == NULL || !access_ok(VERIFY_READ, args, sizeof(struct wrapfs_key_info))) {
		printk("verify_and_copy_args: cannot access args\n");
		rc = -EFAULT;
		goto out;
	}

	/* check access to key */
	if(args->key == NULL || 
		!access_ok(VERIFY_READ, args->key, strnlen_user(args->key, MAX_KEY_LEN))) {
		printk("verify_and_copy_args: cannot access args->key\n");
		rc = -EFAULT;
		goto out;
	}

	/* check whether length of key matches the constraints */
	if((strnlen_user(args->key, MAX_KEY_LEN) < MIN_KEY_LEN) || 
		(strnlen_user(args->key, MAX_KEY_LEN) > MAX_KEY_LEN)) {
		printk("verify_and_copy_args: length of key is too short or too long\n");
		rc = -ENAMETOOLONG;
		goto out;
	}

	/* allocate memory for kargs */
	*kargs = (struct wrapfs_key_info*)kmalloc(sizeof(struct wrapfs_key_info), GFP_KERNEL);
	if(!(*kargs)) {
		printk("verify_and_copy_args: out of memory for kargs\n");
		rc = -ENOMEM;
		goto out;
	}

	/* read key_len from the user address */
	if(get_user(key_len, &(args->key_len))) {
		printk("verify_and_copy_args: cannot read args->key_len\n");
		rc = -EINVAL;
		goto free_kargs;
	}

	/* copy user args to kernel kargs */
	if(copy_from_user(*kargs, args, sizeof(struct wrapfs_key_info))) {
		printk("verify_and_copy_args: cannot copy_from_user for kargs\n");
		rc = -EFAULT;
		goto free_kargs;
	}

	/* copy key to kernel address space */
	(*kargs)->key = getname(args->key);
	if(!(*kargs)->key || IS_ERR((*kargs)->key)) {
		printk("verify_and_copy_args: cannot getname for kargs->key\n");
		rc = PTR_ERR((*kargs)->key);
		goto free_kargs;
	}

	rc=0;
	goto out;

	putname((*kargs)->key);
free_kargs:
	kfree((*kargs));
out:
	return rc;
}
Example #15
0
static elf_addr_t * 
create_elf_tables(char *p, int argc, int envc,
		  struct elfhdr * exec,
		  unsigned long load_addr,
		  unsigned long load_bias,
		  unsigned long interp_load_addr, int ibcs)
{
	elf_caddr_t *argv;
	elf_caddr_t *envp;
	elf_addr_t *sp, *csp;
	char *k_platform, *u_platform;
	long hwcap;
	size_t platform_len = 0;
	size_t len;

	/*
	 * Get hold of platform and hardware capabilities masks for
	 * the machine we are running on.  In some cases (Sparc), 
	 * this info is impossible to get, in others (i386) it is
	 * merely difficult.
	 */

	hwcap = ELF_HWCAP;
	k_platform = ELF_PLATFORM;

	if (k_platform) {
		platform_len = strlen(k_platform) + 1;
		u_platform = p - platform_len;
		__copy_to_user(u_platform, k_platform, platform_len);
	} else
		u_platform = p;

#if defined(__i386__) && defined(CONFIG_SMP)
	/*
	 * In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
	 * by the processes running on the same package. One thing we can do
	 * is to shuffle the initial stack for them.
	 *
	 * The conditionals here are unneeded, but kept in to make the
	 * code behaviour the same as pre change unless we have hyperthreaded
	 * processors. This keeps Mr Marcelo Person happier but should be
	 * removed for 2.5
	 */
	 
	if(smp_num_siblings > 1)
		u_platform = u_platform - ((current->pid % 64) << 7);
#endif	

	/*
	 * Force 16 byte _final_ alignment here for generality.
	 */
	sp = (elf_addr_t *)(~15UL & (unsigned long)(u_platform));
	csp = sp;
	csp -= (1+DLINFO_ITEMS)*2 + (k_platform ? 2 : 0);
#ifdef DLINFO_ARCH_ITEMS
	csp -= DLINFO_ARCH_ITEMS*2;
#endif
	csp -= envc+1;
	csp -= argc+1;
	csp -= (!ibcs ? 3 : 1);	/* argc itself */
	if ((unsigned long)csp & 15UL)
		sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);

	/*
	 * Put the ELF interpreter info on the stack
	 */
#define NEW_AUX_ENT(nr, id, val) \
	  __put_user ((id), sp+(nr*2)); \
	  __put_user ((val), sp+(nr*2+1)); \

	sp -= 2;
	NEW_AUX_ENT(0, AT_NULL, 0);
	if (k_platform) {
		sp -= 2;
		NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
	}
	sp -= DLINFO_ITEMS*2;
	NEW_AUX_ENT( 0, AT_HWCAP, hwcap);
	NEW_AUX_ENT( 1, AT_PAGESZ, ELF_EXEC_PAGESIZE);
	NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC);
	NEW_AUX_ENT( 3, AT_PHDR, load_addr + exec->e_phoff);
	NEW_AUX_ENT( 4, AT_PHENT, sizeof (struct elf_phdr));
	NEW_AUX_ENT( 5, AT_PHNUM, exec->e_phnum);
	NEW_AUX_ENT( 6, AT_BASE, interp_load_addr);
	NEW_AUX_ENT( 7, AT_FLAGS, 0);
	NEW_AUX_ENT( 8, AT_ENTRY, load_bias + exec->e_entry);
	NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid);
	NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
	NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
	NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
#ifdef ARCH_DLINFO
	/* 
	 * ARCH_DLINFO must come last so platform specific code can enforce
	 * special alignment requirements on the AUXV if necessary (eg. PPC).
	 */
	ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT

	sp -= envc+1;
	envp = (elf_caddr_t *) sp;
	sp -= argc+1;
	argv = (elf_caddr_t *) sp;
	if (!ibcs) {
		__put_user((elf_addr_t)(unsigned long) envp,--sp);
		__put_user((elf_addr_t)(unsigned long) argv,--sp);
	}

	__put_user((elf_addr_t)argc,--sp);
	current->mm->arg_start = current->mm->arg_end = (unsigned long) p;
	while (argc-->0) {
		__put_user((elf_caddr_t)(unsigned long)p,argv++);
		len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
		if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
			return NULL;
		p += len;
	}
	__put_user(NULL, argv);
	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
	while (envc-->0) {
		__put_user((elf_caddr_t)(unsigned long)p,envp++);
		len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
		if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
			return NULL;
		p += len;
	}
	__put_user(NULL, envp);
	current->mm->env_end = (unsigned long) p;
	return sp;
}
asmlinkage long xcrypt(void *arg)
{
    if (arg == NULL) {
	printk("User level argument is NULL\n");
	return -EINVAL;
    } else {
	struct myargs *arguments;
	int result, paddedresult, padvalue, preambleWritten, temp, paddingWritten, paddingRead;
	struct file *filp=NULL, *filp1=NULL;
	struct dentry *dentry=NULL, *olddentry=NULL, *newdentry=NULL;
	long int inputFileLen=-1, outputFileLen=-1, keyLen=-1;
	char *srcbuffer, *destbuffer, *padding, *keyFromFile=NULL, *md5_hash=NULL, *tempOutFile;
	umode_t inputFileMode, outputFileMode;
	bool outFileCreated=false, renamed=false, success = false;
	int err=0;	
	arguments = (struct myargs *)kmalloc(sizeof(struct myargs), GFP_KERNEL);
	if (arguments==NULL) {
	    printk("Failed to allocate kernel memory\n");
	    err = -ENOMEM;
	    goto out1;
	}
	result = copy_from_user((void *)arguments, arg, sizeof(struct myargs));
	if(result!=0) {
	    printk("Copying from user failed\n");
	    err = -EFAULT;
	    goto out2;
	}
	if (((struct myargs*)arg)->inputFile == NULL) { /*Checking whether user passed NULL input File*/
	    printk("user level input file argument is NULL\n");
	    err = -EINVAL;
	    goto out2;
	}
	inputFileLen = strnlen_user(((struct myargs*)arg)->inputFile, 32767); //TODO get the maximum value from getname 
	if (inputFileLen == -1) {
	    printk("Finding User inputFile string length Failed\n");
	    err = -EFAULT;
	    goto out2;
	}
	arguments->inputFile = (char *)kmalloc(inputFileLen*sizeof(char), GFP_KERNEL);
	if ((arguments->inputFile)==NULL) {
            printk("Failed to allocate kernel memory for input file\n");
            err = -ENOMEM;
	    goto out2;
        }
	result = strncpy_from_user(arguments->inputFile, ((struct myargs*)arg)->inputFile, inputFileLen);
	if(result!=(inputFileLen-1)) {
            printk("Copying input file string from user failed\n");
            err = -EFAULT;
	    goto out3;
        }
	if((arguments->inputFile)==NULL) {
	    printk("Copying input file string from user failed\n");
	    err = -EFAULT;
	    goto out3;
	}
	if (((struct myargs*)arg)->outputFile == NULL) {
            printk("user level output file argument is NULL\n");
            err = -EINVAL;
	    goto out3;
        }
	outputFileLen = strnlen_user(((struct myargs*)arg)->outputFile, 32767); //TODO get the maximum value from getname
	if (outputFileLen == -1) {
            printk("Finding User outputFile string length Failed\n");
            err = -EFAULT;
	    goto out3;
        }
	arguments->outputFile = (char *)kmalloc(outputFileLen*sizeof(char), GFP_KERNEL);
	if ((arguments->outputFile)==NULL) {
            printk("Failed to allocate kernel memory for outputfile\n");
            err = -ENOMEM;
	    goto out3;
        }
	result = strncpy_from_user(arguments->outputFile, ((struct myargs*)arg)->outputFile, outputFileLen);
	if(result!=(outputFileLen-1)) {
            printk("Copying output file string from user failed\n");
            err = -EFAULT;
	    goto out4;
        }
	if((arguments->outputFile)==NULL) {
            printk("Copying output file string from user failed\n");
            err = -EFAULT;
	    goto out4;
        }
	if (((struct myargs*)arg)->keyBuf == NULL) {
            printk("user level key buffer argument is NULL\n");
            err = -EINVAL;
            goto out4;
        }
	keyLen = strnlen_user(((struct myargs*)arg)->keyBuf, 32767); //TODO get the maximum value from getname
        if (keyLen == -1) {
            printk("Finding User keyBuf string length Failed\n");
            err = -EFAULT;
	    goto out4;
        }
	arguments->keyBuf = (char *)kmalloc(keyLen*sizeof(char), GFP_KERNEL);
	if ((arguments->keyBuf)==NULL) {
            printk("Failed to allocate kernel memory\n");
            err = -ENOMEM;
	    goto out4;
        }
	result = strncpy_from_user(arguments->keyBuf, ((struct myargs*)arg)->keyBuf, keyLen);
	if(result!=(keyLen-1)) {
            printk("Copying key buf string from user failed\n");
            err = -EFAULT;
	    goto out5;
        }
	if((arguments->keyBuf)==NULL) {
            printk("Copying key buf string from user failed\n");
            err = -EFAULT;
	    goto out5;
        }

	if (strlen(arguments->keyBuf) != arguments->keyLen) {
	    printk("User key buffer length and kernel key buffer lengths differ\n");
	    err = -EINVAL;
	    goto out5;
	}

	if((arguments->flags)!=0 && (arguments->flags)!=1) {
	    printk("Invalid values for flag argument, it should be either 1 or 0\n");
	    err = -EINVAL;
	    goto out5;
	}

	srcbuffer = (char *)kmalloc((PAGE_SIZE+1)*sizeof(char), GFP_KERNEL);
	if (srcbuffer==NULL) {
	    printk("Failed to allocate kernel memory for srcbuffer\n");
            err = -ENOMEM;
	    goto out5;
	}
        
        destbuffer = (char *)kmalloc((PAGE_SIZE+1)*sizeof(char), GFP_KERNEL);
        if (destbuffer==NULL) {
            printk("Failed to allocate kernel memory for destbuffer\n");
            err = -ENOMEM;
	    goto out6;
        }

	padding = (char *)kmalloc(4*sizeof(char), GFP_KERNEL);
	if (padding==NULL) {
	    printk("Failed to allocate kernel memory for padding\n");
            err = -ENOMEM;
	    goto out7;
	}

        initialisePadding(padding); /*Initialising the padding array to all 0's */
        
	result=PAGE_SIZE;

	filp = filp_open(arguments->inputFile, O_RDONLY, 0);
	if (PTR_ERR(filp)==-ENOENT) {
	    printk("Input File doesnot exists\n");
	    err = -ENOENT; 
	    goto out8;
	} else {
	    printk("Input File exists\n");
	}
	
        if (!filp || IS_ERR(filp)) {
            printk("Read error for input file %d\n", (int) PTR_ERR(filp));
            err = PTR_ERR(filp);
	    goto out8;
        }

	inputFileMode = filp->f_inode->i_mode;

	if(!S_ISREG(inputFileMode)) {
	    printk("Input File is not a regular file\n");
	    err = -EISDIR;
	    goto out9;
	}

	if (!filp->f_op->read) {
	    printk("Error in reading input file\n");
            err = PTR_ERR(filp);
	    goto out9;
	}

	filp1 = filp_open(arguments->outputFile, O_WRONLY, 0);
	if (PTR_ERR(filp1)==-ENOENT) {
            printk("Output File doesnot exists, creating it\n");
	    filp1 = filp_open(arguments->outputFile, O_CREAT, inputFileMode); /*Creating output file if it doesnot exists with input file permissions*/
	    if(!filp1 || IS_ERR(filp1)) {
		printk("Error in creating output file\n");
		err = PTR_ERR(filp1);
		goto out8_1;
	    } else {
		printk("Output File created succesfully\n");
		outFileCreated = true;
	    }
        } else {
            printk("Output File exists\n");
        }

	if(!outFileCreated) {
	    if(!filp1 || IS_ERR(filp1)) {
		printk("Error in opening output file\n");
		err = PTR_ERR(filp1);
                goto out8_1;
	    }
	}

	if(!outFileCreated) {
	    outputFileMode = filp1->f_inode->i_mode;
	
	    if(!S_ISREG(outputFileMode)) {
                printk("Output File is not a regular file\n");
                err = -EISDIR;
		goto out9;
            }
	}

	if(!outFileCreated) {
	    if (filp->f_inode->i_ino == filp1->f_inode->i_ino) {
	        printk("Both input and output files are same, they should be different\n");
	        err = -EPERM;
		goto out9;
 	    }
	}
	
	if(!outFileCreated) {
	    olddentry = filp1->f_path.dentry;
            filp_close(filp1, NULL);
	    tempOutFile =  (char *)kmalloc((strlen(arguments->outputFile)+5)*sizeof(char), GFP_KERNEL);
	    strncpy(tempOutFile, arguments->outputFile, strlen(arguments->outputFile));
	    strcat(tempOutFile, ".tmp");
	    tempOutFile[(strlen(arguments->outputFile)+5)]='\0';
	    filp1 = filp_open(tempOutFile, O_WRONLY, 0);
            if (PTR_ERR(filp1)==-ENOENT || IS_ERR(filp1)) {
                printk("temp Output File doesnot exists, creating it\n");
            } else {
                printk("temp output File exists, truncating and creating new one\n");
		dentry = filp1->f_path.dentry;
		filp_close(filp1, NULL);
		err = file_unlink(dentry->d_parent->d_inode, dentry);
		if(err != 0) {
		    printk("unlink of already existing temporary file failed\n");
		    err = -EBUSY;
		    goto out9;
		}
		printk("unlink function returned : %d\n", err);
            }
            filp1 = filp_open(tempOutFile, O_CREAT, outputFileMode);
            if(!filp1 || IS_ERR(filp1)) {
                printk("Error in creating temp output file\n");
                err = PTR_ERR(filp1);
		goto out8_1;
            } else {
                printk("temp output File created succesfully\n");
            }
	}
	
	newdentry = filp1->f_path.dentry;

	if (!filp1 || IS_ERR(filp1)) {
            printk("Write error for output file %d\n", (int) PTR_ERR(filp1));
            err = PTR_ERR(filp1);
	    goto out10;
        }

        if (!filp1->f_op->write) {
	    printk("Error in writing to temp output file\n");
            err = PTR_ERR(filp1);
	    goto out10;
	}

	md5_hash = kmalloc(17*sizeof(char), GFP_KERNEL);
	if (md5_hash==NULL) {
            printk("Failed to allocate kernel memory for key from file\n");
            err = -ENOMEM;
	    goto out10;
        }
        err = generate_md5(arguments->keyBuf, md5_hash, strlen(arguments->keyBuf));
	if(err != 0) {
	    printk("kernel MD5 generation failed\n");
	    goto out11;
	}
	md5_hash[strlen(arguments->keyBuf)] = '\0';
        
	if (arguments->flags) { //ENCRYPTION
	    preambleWritten = wrapfs_write_file(filp1, (void *)(md5_hash), strlen(md5_hash)); /*Writing Key hash to the file*/	   
	    if(preambleWritten < 0) {
		printk("Writing preamble failed\n");
		err = -EFAULT;
		goto out11;
	    }
	    paddingWritten = wrapfs_write_file(filp1, (void *)(padding), 4); /*Writing Inital Padding to the file*/
	    if (paddingWritten < 0) {
		printk("Writing padding failed\n");
                err = -EFAULT;
		goto out11;
	    }
	    while(result==PAGE_SIZE) {
	        result = wrapfs_read_file(filp, (void *)srcbuffer, PAGE_SIZE);
		if(result < 0) {
		    printk("Reading from input file failed\n");
                    err = -EFAULT;
		    goto out11;
		}
	        err = encrypt_Cipher(arguments->keyBuf, srcbuffer, destbuffer, result, &paddedresult);
		if (err < 0) {
		    printk("Error occured while encrypting\n");
		    goto out11;
		}
	        if(paddedresult!=result) {
		    padvalue = paddedresult - result;
		    buildPadding(padding, padvalue);
		    result = paddedresult;
	        }
	        result = wrapfs_write_file(filp1, (void *)destbuffer, result);
		if (result < 0) {
		    printk("Writing to output file failed\n");
                    err = -EFAULT;
		    goto out11;
		}
	    }
	    paddingWritten = wrapfs_write_file_pos(filp1, (void *)padding, 4, preambleWritten);
	    if (paddingWritten < 0) {
                printk("Writing padding failed\n");
                err = -EFAULT;
		goto out11;
            }
	} else {  //DECRYPTION
	    keyFromFile = kmalloc(16*sizeof(char), GFP_KERNEL);
	    if (keyFromFile==NULL) {
                printk("Failed to allocate kernel memory for key from file\n");
                err = -ENOMEM;
		goto out11;
            }
	    temp = wrapfs_read_file(filp, (void *)keyFromFile, strlen(md5_hash));
	    if (temp != strlen(md5_hash)) {
		printk("reading key from file failed\n");
		err = -EFAULT;
		goto out12;
	    }
	    if (compareKeys(md5_hash, keyFromFile, temp)) {
		printk("Both Keys Match\n");
	    } else {
		printk("Both keys doesnot match\n");
		err = -EINVAL; //TODO : Return proper error Value.
		goto out12;
	    }
	    paddingRead = wrapfs_read_file(filp, (void *)padding, 4);
	    if(paddingRead < 0) {
		printk("Reading padding failed\n");
                err = -EFAULT;
		goto out12;
	    }
	    padvalue = reconstructPadding(padding);
	    if (padvalue < 0) {
		printk("Reconstructing padding value failed(negative value not acceptable)\n");
                err = -EFAULT;
		goto out12;
	    }
	    printk("Pad value returned : %d\n", padvalue);
	    while(result==PAGE_SIZE) {
                result = wrapfs_read_file(filp, (void *)srcbuffer, PAGE_SIZE);
		if (result < 0) {
		    printk("Reading from input file failed\n");
                    err = -EFAULT;
		    goto out12;
		}
                printk("result read from file : %u\n", result);
                err = decrypt_Cipher(arguments->keyBuf, srcbuffer, destbuffer, result);
		if (err < 0) {
                    printk("Error occured while encrypting\n");
                    goto out12;
                }	
		if (result<PAGE_SIZE) {
		    result = result - padvalue;
		}
                result = wrapfs_write_file(filp1, (void *)destbuffer, result);
		if(result < 0) {
		    printk("writing to output file failed\n");
                    err = -EFAULT; //TODO goto
		    goto out12;
		}
            }
	}
	if(!outFileCreated) {
	    err = file_rename(newdentry->d_parent->d_inode, newdentry, olddentry->d_parent->d_inode, olddentry);
	    if(err!=0) {
		printk("renaming of tempfile to output file failed\n");
                err = -EBUSY;
		goto out12;
	    } else
		renamed = true;
        } else
	    success = true;

out12:
	if(keyFromFile)
	    kfree(keyFromFile);
out11:
	kfree(md5_hash);
out10:
	if(filp1)
	    filp_close(filp1, NULL);
	if((!renamed && !outFileCreated)||(!success && outFileCreated))
	    file_unlink(newdentry->d_parent->d_inode, newdentry);
out9:
	if(filp1)
	    filp_close(filp1, NULL);
out8_1:
	if(filp)
	    filp_close(filp, NULL);
out8:
	kfree(padding);
out7:
	kfree(destbuffer);
out6:
	kfree(srcbuffer);
out5:
	kfree(arguments->keyBuf);
out4:
	kfree(arguments->outputFile);
out3:
	kfree(arguments->inputFile);
out2:
 	kfree(arguments);
out1:
	return err;
    }
}
Example #17
0
File: exec.c Project: jmgc/noah
DEFINE_SYSCALL(execve, gstr_t, gelf_path, gaddr_t, gargv, gaddr_t, genvp)
{
  int err;
  char elf_path[LINUX_PATH_MAX];
  strncpy_from_user(elf_path, gelf_path, sizeof elf_path);

  size_t argv_rsrv = 1024;
  char **argv = malloc(sizeof(char *) * argv_rsrv);
  size_t argc = 0;
  while (true) {
    size_t i = argc;
    gaddr_t addr;
    if (copy_from_user(&addr, gargv + sizeof(gaddr_t) * i, sizeof addr)) {
      err = -LINUX_EFAULT;
      goto faile_copy_argv;
    }
    if (addr == 0)
      break;
    argc++;
    if (argc + 1 > LINUX_MAX_ARG_STRINGS) {
      err = -LINUX_E2BIG;
      goto faile_copy_argv;
    }
    if (argc + 1 > argv_rsrv) {
      argv_rsrv *= 2;
      argv = realloc(argv, sizeof(char *) * argv_rsrv);
    }
    int size = strnlen_user(addr, LINUX_MAX_ARG_STRLEN);
    if (size == 0) {
      err = -LINUX_EFAULT;
      goto faile_copy_argv;
    }
    if (size > LINUX_MAX_ARG_STRLEN) {
      err = -LINUX_E2BIG;
      goto faile_copy_argv;
    }
    argv[i] = alloca(size);
    copy_from_user(argv[i], addr, size); /* always success */
  }
  argv[argc] = NULL;

  size_t envp_rsrv = 1024;
  char **envp = malloc(sizeof(char *) * envp_rsrv);
  size_t envc = 0;
  while (true) {
    size_t i = envc;
    gaddr_t addr;
    if (copy_from_user(&addr, genvp + sizeof(gaddr_t) * i, sizeof addr)) {
      err = -LINUX_EFAULT;
      goto fail_copy_envp;
    }
    if (addr == 0)
      break;
    envc++;
    if (envc + 1 > LINUX_MAX_ARG_STRINGS) {
      err = -LINUX_E2BIG;
      goto fail_copy_envp;
    }
    if (envc + 1 > envp_rsrv) {
      envp_rsrv *= 2;
      envp = realloc(envp, sizeof(char *) * envp_rsrv);
    }
    int size = strnlen_user(addr, LINUX_MAX_ARG_STRLEN);
    if (size == 0) {
      err = -LINUX_EFAULT;
      goto fail_copy_envp;
    }
    if (size > LINUX_MAX_ARG_STRLEN) {
      err = -LINUX_E2BIG;
      goto fail_copy_envp;
    }
    envp[i] = alloca(size);
    copy_from_user(envp[i], addr, size); /* always success */
  }
  envp[envc] = NULL;

  err = do_exec(elf_path, argc, argv, envp);
  if (err < 0) {
    goto fail_copy_envp;
  }

  uint64_t entry;
  vmm_read_register(HV_X86_RIP, &entry);
  vmm_write_register(HV_X86_RIP, entry - 2); // because syscall handler adds 2 to current rip when returning to vmm_run

 fail_copy_envp:
  free(envp);
 faile_copy_argv:
  free(argv);
  return err;
}
Example #18
0
static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
				 unsigned long arg, void __user *p)
{
	int			retval;
	struct uinput_device	*udev = file->private_data;
	struct uinput_ff_upload ff_up;
	struct uinput_ff_erase  ff_erase;
	struct uinput_request   *req;
	int                     length;
	char			*phys;

	retval = mutex_lock_interruptible(&udev->mutex);
	if (retval)
		return retval;

	if (!udev->dev) {
		retval = uinput_allocate_device(udev);
		if (retval)
			goto out;
	}

	switch (cmd) {
		case UI_DEV_CREATE:
			retval = uinput_create_device(udev);
			break;

		case UI_DEV_DESTROY:
			uinput_destroy_device(udev);
			break;

		case UI_SET_EVBIT:
			retval = uinput_set_bit(arg, evbit, EV_MAX);
			break;

		case UI_SET_KEYBIT:
			retval = uinput_set_bit(arg, keybit, KEY_MAX);
			break;

		case UI_SET_RELBIT:
			retval = uinput_set_bit(arg, relbit, REL_MAX);
			break;

		case UI_SET_ABSBIT:
			retval = uinput_set_bit(arg, absbit, ABS_MAX);
			break;

		case UI_SET_MSCBIT:
			retval = uinput_set_bit(arg, mscbit, MSC_MAX);
			break;

		case UI_SET_LEDBIT:
			retval = uinput_set_bit(arg, ledbit, LED_MAX);
			break;

		case UI_SET_SNDBIT:
			retval = uinput_set_bit(arg, sndbit, SND_MAX);
			break;

		case UI_SET_FFBIT:
			retval = uinput_set_bit(arg, ffbit, FF_MAX);
			break;

		case UI_SET_SWBIT:
			retval = uinput_set_bit(arg, swbit, SW_MAX);
			break;

		case UI_SET_PHYS:
			if (udev->state == UIST_CREATED) {
				retval = -EINVAL;
				goto out;
			}
			length = strnlen_user(p, 1024);
			if (length <= 0) {
				retval = -EFAULT;
				break;
			}
			kfree(udev->dev->phys);
			udev->dev->phys = phys = kmalloc(length, GFP_KERNEL);
			if (!phys) {
				retval = -ENOMEM;
				break;
			}
			if (copy_from_user(phys, p, length)) {
				udev->dev->phys = NULL;
				kfree(phys);
				retval = -EFAULT;
				break;
			}
			phys[length - 1] = '\0';
			break;

		case UI_BEGIN_FF_UPLOAD:
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
				break;

			req = uinput_request_find(udev, ff_up.request_id);
			if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
				retval = -EINVAL;
				break;
			}

			ff_up.retval = 0;
			ff_up.effect = *req->u.upload.effect;
			if (req->u.upload.old)
				ff_up.old = *req->u.upload.old;
			else
				memset(&ff_up.old, 0, sizeof(struct ff_effect));

			retval = uinput_ff_upload_to_user(p, &ff_up);
			break;

		case UI_BEGIN_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			req = uinput_request_find(udev, ff_erase.request_id);
			if (!req || req->code != UI_FF_ERASE) {
				retval = -EINVAL;
				break;
			}

			ff_erase.retval = 0;
			ff_erase.effect_id = req->u.effect_id;
			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			break;

		case UI_END_FF_UPLOAD:
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
				break;

			req = uinput_request_find(udev, ff_up.request_id);
			if (!req || req->code != UI_FF_UPLOAD ||
			    !req->u.upload.effect) {
				retval = -EINVAL;
				break;
			}

			req->retval = ff_up.retval;
			uinput_request_done(udev, req);
			break;

		case UI_END_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			req = uinput_request_find(udev, ff_erase.request_id);
			if (!req || req->code != UI_FF_ERASE) {
				retval = -EINVAL;
				break;
			}

			req->retval = ff_erase.retval;
			uinput_request_done(udev, req);
			break;

		default:
			retval = -EINVAL;
	}

 out:
	mutex_unlock(&udev->mutex);
	return retval;
}
/*
 * present useful information to the program
 */
static int create_elf_fdpic_tables(struct linux_binprm *bprm,
				   struct mm_struct *mm,
				   struct elf_fdpic_params *exec_params,
				   struct elf_fdpic_params *interp_params)
{
	unsigned long sp, csp, nitems;
	elf_caddr_t *argv, *envp;
	size_t platform_len = 0, len;
	char *k_platform, *u_platform, *p;
	long hwcap;
	int loop;

	/* we're going to shovel a whole load of stuff onto the stack */
#ifdef CONFIG_MMU
	sp = bprm->p;
#else
	sp = mm->start_stack;

	/* stack the program arguments and environment */
	if (elf_fdpic_transfer_args_to_stack(bprm, &sp) < 0)
		return -EFAULT;
#endif

	/* get hold of platform and hardware capabilities masks for the machine
	 * we are running on.  In some cases (Sparc), this info is impossible
	 * to get, in others (i386) it is merely difficult.
	 */
	hwcap = ELF_HWCAP;
	k_platform = ELF_PLATFORM;

	if (k_platform) {
		platform_len = strlen(k_platform) + 1;
		sp -= platform_len;
		if (__copy_to_user(u_platform, k_platform, platform_len) != 0)
			return -EFAULT;
	}

	u_platform = (char *) sp;

#if defined(__i386__) && defined(CONFIG_SMP)
	/* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
	 * by the processes running on the same package. One thing we can do
	 * is to shuffle the initial stack for them.
	 *
	 * the conditionals here are unneeded, but kept in to make the
	 * code behaviour the same as pre change unless we have hyperthreaded
	 * processors. This keeps Mr Marcelo Person happier but should be
	 * removed for 2.5
	 */
	if (smp_num_siblings > 1)
		sp = sp - ((current->pid % 64) << 7);
#endif

	sp &= ~7UL;

	/* stack the load map(s) */
	len = sizeof(struct elf32_fdpic_loadmap);
	len += sizeof(struct elf32_fdpic_loadseg) * exec_params->loadmap->nsegs;
	sp = (sp - len) & ~7UL;
	exec_params->map_addr = sp;

	if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0)
		return -EFAULT;

	current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;

	if (interp_params->loadmap) {
		len = sizeof(struct elf32_fdpic_loadmap);
		len += sizeof(struct elf32_fdpic_loadseg) * interp_params->loadmap->nsegs;
		sp = (sp - len) & ~7UL;
		interp_params->map_addr = sp;

		if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0)
			return -EFAULT;

		current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
	}

	/* force 16 byte _final_ alignment here for generality */
#define DLINFO_ITEMS 13

	nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0);
#ifdef DLINFO_ARCH_ITEMS
	nitems += DLINFO_ARCH_ITEMS;
#endif

	csp = sp;
	sp -= nitems * 2 * sizeof(unsigned long);
	sp -= (bprm->envc + 1) * sizeof(char *);	/* envv[] */
	sp -= (bprm->argc + 1) * sizeof(char *);	/* argv[] */
	sp -= 1 * sizeof(unsigned long);		/* argc */

	csp -= sp & 15UL;
	sp -= sp & 15UL;

	/* put the ELF interpreter info on the stack */
#define NEW_AUX_ENT(nr, id, val)						\
	do {									\
		struct { unsigned long _id, _val; } *ent = (void *) csp;	\
		__put_user((id), &ent[nr]._id);					\
		__put_user((val), &ent[nr]._val);				\
	} while (0)

	csp -= 2 * sizeof(unsigned long);
	NEW_AUX_ENT(0, AT_NULL, 0);
	if (k_platform) {
		csp -= 2 * sizeof(unsigned long);
		NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
	}

	csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
	NEW_AUX_ENT( 0, AT_HWCAP,		hwcap);
	NEW_AUX_ENT( 1, AT_PAGESZ,		PAGE_SIZE);
	NEW_AUX_ENT( 2, AT_CLKTCK,		CLOCKS_PER_SEC);
	NEW_AUX_ENT( 3, AT_PHDR,		exec_params->ph_addr);
	NEW_AUX_ENT( 4, AT_PHENT,		sizeof(struct elf_phdr));
	NEW_AUX_ENT( 5, AT_PHNUM,		exec_params->hdr.e_phnum);
	NEW_AUX_ENT( 6,	AT_BASE,		interp_params->elfhdr_addr);
	NEW_AUX_ENT( 7, AT_FLAGS,		0);
	NEW_AUX_ENT( 8, AT_ENTRY,		exec_params->entry_addr);
	NEW_AUX_ENT( 9, AT_UID,			(elf_addr_t) current->uid);
	NEW_AUX_ENT(10, AT_EUID,		(elf_addr_t) current->euid);
	NEW_AUX_ENT(11, AT_GID,			(elf_addr_t) current->gid);
	NEW_AUX_ENT(12, AT_EGID,		(elf_addr_t) current->egid);

#ifdef ARCH_DLINFO
	/* ARCH_DLINFO must come last so platform specific code can enforce
	 * special alignment requirements on the AUXV if necessary (eg. PPC).
	 */
	ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT

	/* allocate room for argv[] and envv[] */
	csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
	envp = (elf_caddr_t *) csp;
	csp -= (bprm->argc + 1) * sizeof(elf_caddr_t);
	argv = (elf_caddr_t *) csp;

	/* stack argc */
	csp -= sizeof(unsigned long);
	__put_user(bprm->argc, (unsigned long *) csp);

	if (csp != sp)
		BUG();

	/* fill in the argv[] array */
#ifdef CONFIG_MMU
	current->mm->arg_start = bprm->p;
#else
	current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
#endif

	p = (char *) current->mm->arg_start;
	for (loop = bprm->argc; loop > 0; loop--) {
		__put_user((elf_caddr_t) p, argv++);
		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
		if (!len || len > PAGE_SIZE * MAX_ARG_PAGES)
			return -EINVAL;
		p += len;
	}
	__put_user(NULL, argv);
	current->mm->arg_end = (unsigned long) p;

	/* fill in the envv[] array */
	current->mm->env_start = (unsigned long) p;
	for (loop = bprm->envc; loop > 0; loop--) {
		__put_user((elf_caddr_t)(unsigned long) p, envp++);
		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
		if (!len || len > PAGE_SIZE * MAX_ARG_PAGES)
			return -EINVAL;
		p += len;
	}
	__put_user(NULL, envp);
	current->mm->env_end = (unsigned long) p;

	mm->start_stack = (unsigned long) sp;
	return 0;
} /* end create_elf_fdpic_tables() */
Example #20
0
/*
 * create_elf_tables
 */
static int
create_elf_tables_aux(struct linux_binprm *bprm,
                      unsigned long ntdll_load_addr, elf_off_t ntdll_phoff, elf_half_t ntdll_phnum, unsigned long ntdll_start_thunk,
                      unsigned long exeso_load_addr, elf_off_t exeso_phoff, elf_half_t exeso_phnum, unsigned long exeso_start_thunk,
                      unsigned long interp_load_addr, unsigned long interp_entry, unsigned long init_entry)
{
    unsigned long p = bprm->p;
    int argc = bprm->argc;
    int envc = bprm->envc;
    elf_addr_t __user *argv;
    elf_addr_t __user *envp;
    elf_addr_t __user *sp;
    elf_addr_t __user *u_platform;
    const char *k_platform = ELF_PLATFORM;
    int items;
    elf_addr_t *elf_info;
    elf_addr_t *elf_info2;
    int ei_index = 0;
    const struct cred *cred = current_cred();

    /*
     * If this architecture has a platform capability string, copy it
     * to userspace.  In some cases (Sparc), this info is impossible
     * for userspace to get any other way, in others (i386) it is
     * merely difficult.
     */

    u_platform = NULL;
    if (k_platform) {
        size_t len = strlen(k_platform) + 1;

        /*
         * In some cases (e.g. Hyper-Threading), we want to avoid L1
         * evictions by the processes running on the same package. One
         * thing we can do is to shuffle the initial stack for them.
         */

        p = arch_align_stack(p);

        u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
        if (__copy_to_user(u_platform, k_platform, len))
            return -EFAULT;
    }

    /* Create the ELF interpreter info */
    elf_info = (elf_addr_t *) current->mm->saved_auxv;
#define NEW_AUX_ENT(id, val) \
	do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0)

#ifdef ARCH_DLINFO11
    /*
     * ARCH_DLINFO must come first so PPC can do its special alignment of
     * AUXV.
     */
    ARCH_DLINFO;
#endif
    NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
    NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
    NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
    NEW_AUX_ENT(AT_PHDR, ntdll_load_addr + ntdll_phoff);
    NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
    NEW_AUX_ENT(AT_PHNUM, ntdll_phnum);
    NEW_AUX_ENT(AT_BASE, interp_load_addr);
    NEW_AUX_ENT(AT_FLAGS, 0);
    NEW_AUX_ENT(AT_ENTRY, ntdll_start_thunk);
    NEW_AUX_ENT(AT_UID, cred->uid);
    NEW_AUX_ENT(AT_EUID, cred->euid);
    NEW_AUX_ENT(AT_GID, cred->gid);
    NEW_AUX_ENT(AT_EGID, cred->egid);
    NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));
#if 0
    if (k_platform) {
        /* FIXME */
        NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform);
    }
#endif
    if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
        NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data);
    }
#undef NEW_AUX_ENT
    /* AT_NULL is zero; clear the rest too */
    memset(&elf_info[ei_index], 0,
           sizeof current->mm->saved_auxv - ei_index * sizeof elf_info[0]);

    /* And advance past the AT_NULL entry.  */
    ei_index += 2;

    sp = STACK_ADD(p, ei_index * 2);

    items = (argc + 1) + (envc + 1);
    items += 1; /* ELF interpreters only put argc on the stack */
    items += 3; /* interp entry address & _init address & load_base */
    bprm->p = STACK_ROUND(sp, items);

    /* Point sp at the lowest address on the stack */
#ifdef CONFIG_STACK_GROWSUP
    sp = (elf_addr_t __user *)bprm->p - items - ei_index;
    bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */
#else
    sp = (elf_addr_t __user *)bprm->p;
#endif

    /* Now, let's put argc (and argv, envp if appropriate) on the stack */
    if (__put_user(argc, sp))
        return -EFAULT;
    ++sp;
    argv = sp;
    envp = argv + argc + 1;

    /* Populate argv and envp */
    p = current->mm->arg_end = current->mm->arg_start;
    while (argc-- > 0) {
        size_t len;
        __put_user((elf_addr_t)p, argv);
        ++argv;
        len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
        if (!len || len > MAX_ARG_STRLEN)
            return 0;
        p += len;
    }
    if (__put_user(0, argv))
        return -EFAULT;
    current->mm->arg_end = current->mm->env_start = p;
    while (envc-- > 0) {
        size_t len;
        __put_user((elf_addr_t)p, envp);
        ++envp;
        len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
        if (!len || len > MAX_ARG_STRLEN)
            return 0;
        p += len;
    }
    if (__put_user(0, envp))
        return -EFAULT;
    current->mm->env_end = p;

    /* Put the elf_info on the stack in the right place.  */
    sp = (elf_addr_t __user *)envp + 1;
    if (copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t)))
        return -EFAULT;
    sp += ei_index;


    elf_info2 = (elf_addr_t *)kmalloc(sizeof(current->mm->saved_auxv), GFP_KERNEL);
    if(!elf_info2)
        return -ENOMEM;

    ei_index = 0;
#define NEW_AUX_ENT(id, val) \
	do { elf_info2[ei_index++] = id; elf_info2[ei_index++] = val; } while (0)

#ifdef ARCH_DLINFO11
    /*
     * ARCH_DLINFO must come first so PPC can do its special alignment of
     * AUXV.
     */
    ARCH_DLINFO;
#endif
    NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
    NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
    NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
    NEW_AUX_ENT(AT_PHDR, exeso_load_addr + exeso_phoff);
    NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
    NEW_AUX_ENT(AT_PHNUM, exeso_phnum);
    NEW_AUX_ENT(AT_BASE, interp_load_addr);
    NEW_AUX_ENT(AT_FLAGS, 0);
    NEW_AUX_ENT(AT_ENTRY, exeso_start_thunk);
    NEW_AUX_ENT(AT_UID, cred->uid);
    NEW_AUX_ENT(AT_EUID, cred->euid);
    NEW_AUX_ENT(AT_GID, cred->gid);
    NEW_AUX_ENT(AT_EGID, cred->egid);
    NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));
#if 0
    if (k_platform) {
        /* FIXME */
        NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform);
    }
#endif
    if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
        NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data);
    }
#undef NEW_AUX_ENT
    /* AT_NULL is zero; clear the rest too */
    memset(&elf_info2[ei_index], 0,
           sizeof(current->mm->saved_auxv) - ei_index * sizeof elf_info2[0]);
    ei_index += 2;
    if (copy_to_user(sp, elf_info2, ei_index * sizeof(elf_addr_t))) {
        kfree(elf_info2);
        return -EFAULT;
    }
    kfree(elf_info2);
    sp += ei_index;

    __put_user(interp_entry, sp);
    ++sp;
    __put_user(init_entry, sp);
    ++sp;
    __put_user(exeso_load_addr, sp);

    memset(current->mm->saved_auxv, 0, sizeof(current->mm->saved_auxv));

    return 0;
} /* end create_elf_tables */
Example #21
0
/*
 * search the process keyrings for a matching key
 * - nested keyrings may also be searched if they have Search permission
 * - if a key is found, it will be attached to the destination keyring if
 *   there's one specified
 * - /sbin/request-key will be invoked if _callout_info is non-NULL
 *   - the _callout_info string will be passed to /sbin/request-key
 *   - if the _callout_info string is empty, it will be rendered as "-"
 * - implements request_key()
 */
asmlinkage long sys_request_key(const char __user *_type,
				const char __user *_description,
				const char __user *_callout_info,
				key_serial_t destringid)
{
	struct key_type *ktype;
	struct key *key;
	key_ref_t dest_ref;
	char type[32], *description, *callout_info;
	long dlen, ret;

	/* pull the type into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EPERM;
	if (type[0] == '.')
		goto error;

	/* pull the description into kernel space */
	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* pull the callout info into kernel space */
	callout_info = NULL;
	if (_callout_info) {
		ret = -EFAULT;
		dlen = strnlen_user(_callout_info, PAGE_SIZE - 1);
		if (dlen <= 0)
			goto error2;

		ret = -EINVAL;
		if (dlen > PAGE_SIZE - 1)
			goto error2;

		ret = -ENOMEM;
		callout_info = kmalloc(dlen + 1, GFP_KERNEL);
		if (!callout_info)
			goto error2;

		ret = -EFAULT;
		if (copy_from_user(callout_info, _callout_info, dlen + 1) != 0)
			goto error3;
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key = request_key_and_link(ktype, description, callout_info,
				   key_ref_to_ptr(dest_ref));
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error5;
	}

	ret = key->serial;

 	key_put(key);
 error5:
	key_type_put(ktype);
 error4:
	key_ref_put(dest_ref);
 error3:
	kfree(callout_info);
 error2:
	kfree(description);
 error:
	return ret;

} /* end sys_request_key() */
Example #22
0
/*
 * search the specified keyring for a matching key
 * - the start keyring must be searchable
 * - nested keyrings may also be searched if they are searchable
 * - only keys with search permission may be found
 * - if a key is found, it will be attached to the destination keyring if
 *   there's one specified
 * - implements keyctl(KEYCTL_SEARCH)
 */
long keyctl_keyring_search(key_serial_t ringid,
			   const char __user *_type,
			   const char __user *_description,
			   key_serial_t destringid)
{
	struct key_type *ktype;
	key_ref_t keyring_ref, key_ref, dest_ref;
	char type[32], *description;
	long dlen, ret;

	/* pull the type and description into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* get the keyring at which to begin the search */
	keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error2;
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key_ref = keyring_search(keyring_ref, ktype, description);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);

		/* treat lack or presence of a negative key the same */
		if (ret == -EAGAIN)
			ret = -ENOKEY;
		goto error5;
	}

	/* link the resulting key to the destination keyring if we can */
	if (dest_ref) {
		ret = key_permission(key_ref, KEY_LINK);
		if (ret < 0)
			goto error6;

		ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
		if (ret < 0)
			goto error6;
	}

	ret = key_ref_to_ptr(key_ref)->serial;

 error6:
	key_ref_put(key_ref);
 error5:
	key_type_put(ktype);
 error4:
	key_ref_put(dest_ref);
 error3:
	key_ref_put(keyring_ref);
 error2:
	kfree(description);
 error:
	return ret;

} /* end keyctl_keyring_search() */
Example #23
0
/*
 * extract the description of a new key from userspace and either add it as a
 * new key to the specified keyring or update a matching key in that keyring
 * - the keyring must be writable
 * - returns the new key's serial number
 * - implements add_key()
 */
asmlinkage long sys_add_key(const char __user *_type,
			    const char __user *_description,
			    const void __user *_payload,
			    size_t plen,
			    key_serial_t ringid)
{
	key_ref_t keyring_ref, key_ref;
	char type[32], *description;
	void *payload;
	long dlen, ret;

	ret = -EINVAL;
	if (plen > 32767)
		goto error;

	/* draw all the data into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EPERM;
	if (type[0] == '.')
		goto error;

	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* pull the payload in if one was supplied */
	payload = NULL;

	if (_payload) {
		ret = -ENOMEM;
		payload = kmalloc(plen, GFP_KERNEL);
		if (!payload)
			goto error2;

		ret = -EFAULT;
		if (copy_from_user(payload, _payload, plen) != 0)
			goto error3;
	}

	/* find the target keyring (which must be writable) */
	keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error3;
	}

	/* create or update the requested key and add it to the target
	 * keyring */
	key_ref = key_create_or_update(keyring_ref, type, description,
				       payload, plen, 0);
	if (!IS_ERR(key_ref)) {
		ret = key_ref_to_ptr(key_ref)->serial;
		key_ref_put(key_ref);
	}
	else {
		ret = PTR_ERR(key_ref);
	}

	key_ref_put(keyring_ref);
 error3:
	kfree(payload);
 error2:
	kfree(description);
 error:
	return ret;

} /* end sys_add_key() */