/* 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; }
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)); }
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; }
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; }
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; }
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; }
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; }
/** * 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); }
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; }
/* * 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; }
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; }
/* * 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() */
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; }
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; } }
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; }
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() */
/* * 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 */
/* * 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() */
/* * 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() */
/* * 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() */