static int sys_rename(rename_args_t *arg) { rename_args_t kern_args; char *oldname; char *newname; int err; if ((err = copy_from_user(&kern_args, arg, sizeof(rename_args_t))) < 0) { curthr->kt_errno = -err; return -1; } oldname = user_strdup(&kern_args.oldname); if (!oldname) { curthr->kt_errno = EINVAL; return -1; } newname = user_strdup(&kern_args.newname); if (!newname) { curthr->kt_errno = EINVAL; kfree(oldname); return -1; } err = do_rename(oldname, newname); kfree(newname); kfree(oldname); if (err < 0) { curthr->kt_errno = -err; return -1; } else return err; }
static int sys_link(link_args_t *arg) { link_args_t kern_args; char *to; char *from; int err; if ((err = copy_from_user(&kern_args, arg, sizeof(link_args_t))) < 0) { curthr->kt_errno = -err; return -1; } to = user_strdup(&kern_args.to); if (!to) { curthr->kt_errno = EINVAL; return -1; } from = user_strdup(&kern_args.from); if (!from) { curthr->kt_errno = EINVAL; kfree(to); return -1; } err = do_link(from, to); kfree(to); kfree(from); if (err < 0) { curthr->kt_errno = -err; return -1; } else { return err; } }
static int sys_stat(stat_args_t *arg) { stat_args_t kern_args; struct stat buf; char *path; int ret; if (copy_from_user(&kern_args, arg, sizeof(kern_args)) < 0) { curthr->kt_errno = EFAULT; return -1; } if ((path = user_strdup(&kern_args.path)) == NULL) { curthr->kt_errno = EINVAL; return -1; } ret = do_stat(path, &buf); if (ret == 0) { ret = copy_to_user(kern_args.buf, &buf, sizeof(struct stat)); } if (ret != 0) { kfree(path); curthr->kt_errno = -ret; return -1; } kfree(path); return 0; }
static int sys_chdir(argstr_t *arg) { argstr_t kern_args; char *path; int err; if ((err = copy_from_user(&kern_args, arg, sizeof(argstr_t))) < 0) { curthr->kt_errno = -err; return -1; } path = user_strdup(&kern_args); if (!path) { curthr->kt_errno = EINVAL; return -1; } err = do_chdir(path); kfree(path); if (err < 0) { curthr->kt_errno = -err; return -1; } else return err; }
static int sys_umount(argstr_t *input) { argstr_t kstr; char *target; int ret; if (copy_from_user(&kstr, input, sizeof(kstr)) < 0) { curthr->kt_errno = EFAULT; return -1; } if (NULL == (target = user_strdup(&kstr))) { curthr->kt_errno = EINVAL; return -1; } ret = do_umount(target); kfree(target); if (ret) { curthr->kt_errno = -ret; return -1; } return 0; }
/* user_strdup, but this handles the errno. 0 on failure, ptr on success */ char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen) { void *k_string = user_strdup(p, u_string, strlen); if (IS_ERR(k_string)) { set_errno(-PTR_ERR(k_string)); return NULL; } return k_string; }
static int sys_mount(mount_args_t *arg) { mount_args_t kern_args; char *source; char *target; char *type; int ret; if (copy_from_user(&kern_args, arg, sizeof(kern_args)) < 0) { curthr->kt_errno = EFAULT; return -1; } /* null is okay only for the source */ source = user_strdup(&kern_args.spec); if (NULL == (target = user_strdup(&kern_args.dir))) { kfree(source); curthr->kt_errno = EINVAL; return -1; } if (NULL == (type = user_strdup(&kern_args.fstype))) { kfree(source); kfree(target); curthr->kt_errno = EINVAL; return -1; } ret = do_mount(source, target, type); kfree(source); kfree(target); kfree(type); if (ret) { curthr->kt_errno = -ret; return -1; } return 0; }
static int sys_debug(argstr_t *arg) { argstr_t kern_args; int err; char *message; if ((err = copy_from_user(&kern_args, arg, sizeof(argstr_t))) < 0) { curthr->kt_errno = -err; return -1; } message = user_strdup(&kern_args); dbg(DBG_USER, "%s\n", message); kfree(message); return 0; }
static int sys_execve(execve_args_t *args, regs_t *regs) { execve_args_t kern_args; char *kern_filename = NULL; char **kern_argv = NULL; char **kern_envp = NULL; int err; if ((err = copy_from_user(&kern_args, args, sizeof(kern_args))) < 0) { curthr->kt_errno = -err; goto cleanup; } /* copy the name of the executable */ if ((kern_filename = user_strdup(&kern_args.filename)) == NULL) goto cleanup; /* copy the argument list */ if (kern_args.argv.av_vec) { if ((kern_argv = user_vecdup(&kern_args.argv)) == NULL) goto cleanup; } /* copy the environment list */ if (kern_args.envp.av_vec) { if ((kern_envp = user_vecdup(&kern_args.envp)) == NULL) goto cleanup; } err = do_execve(kern_filename, kern_argv, kern_envp, regs); curthr->kt_errno = -err; cleanup: if (kern_filename) kfree(kern_filename); if (kern_argv) free_vector(kern_argv); if (kern_envp) free_vector(kern_envp); if (curthr->kt_errno) return -1; return 0; }
static int sys_open(open_args_t *arg) { open_args_t kern_args; char *path; int err; if ((err = copy_from_user(&kern_args, arg, sizeof(open_args_t))) < 0) { curthr->kt_errno = -err; return -1; } path = user_strdup(&kern_args.filename); if (!path) { curthr->kt_errno = EINVAL; return -1; } err = do_open(path, kern_args.flags); kfree(path); if (err < 0) { curthr->kt_errno = -err; return -1; } else return err; }