Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linux/linux_misc.c
Show First 20 Lines • Show All 468 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
#ifdef LINUX_LEGACY_SYSCALLS | #ifdef LINUX_LEGACY_SYSCALLS | ||||
int | int | ||||
linux_utime(struct thread *td, struct linux_utime_args *args) | linux_utime(struct thread *td, struct linux_utime_args *args) | ||||
{ | { | ||||
struct timeval tv[2], *tvp; | struct timeval tv[2], *tvp; | ||||
struct l_utimbuf lut; | struct l_utimbuf lut; | ||||
char *fname; | |||||
int error; | int error; | ||||
if (args->times) { | if (args->times) { | ||||
if ((error = copyin(args->times, &lut, sizeof lut)) != 0) | if ((error = copyin(args->times, &lut, sizeof lut)) != 0) | ||||
return (error); | return (error); | ||||
tv[0].tv_sec = lut.l_actime; | tv[0].tv_sec = lut.l_actime; | ||||
tv[0].tv_usec = 0; | tv[0].tv_usec = 0; | ||||
tv[1].tv_sec = lut.l_modtime; | tv[1].tv_sec = lut.l_modtime; | ||||
tv[1].tv_usec = 0; | tv[1].tv_usec = 0; | ||||
tvp = tv; | tvp = tv; | ||||
} else | } else | ||||
tvp = NULL; | tvp = NULL; | ||||
if (!LUSECONVPATH(td)) { | return (kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, | ||||
error = kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, | tvp, UIO_SYSSPACE)); | ||||
tvp, UIO_SYSSPACE); | |||||
} else { | |||||
LCONVPATHEXIST(args->fname, &fname); | |||||
error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, tvp, | |||||
UIO_SYSSPACE); | |||||
LFREEPATH(fname); | |||||
} | } | ||||
return (error); | |||||
} | |||||
#endif | #endif | ||||
#ifdef LINUX_LEGACY_SYSCALLS | #ifdef LINUX_LEGACY_SYSCALLS | ||||
int | int | ||||
linux_utimes(struct thread *td, struct linux_utimes_args *args) | linux_utimes(struct thread *td, struct linux_utimes_args *args) | ||||
{ | { | ||||
l_timeval ltv[2]; | l_timeval ltv[2]; | ||||
struct timeval tv[2], *tvp = NULL; | struct timeval tv[2], *tvp = NULL; | ||||
char *fname; | |||||
int error; | int error; | ||||
if (args->tptr != NULL) { | if (args->tptr != NULL) { | ||||
if ((error = copyin(args->tptr, ltv, sizeof ltv)) != 0) | if ((error = copyin(args->tptr, ltv, sizeof ltv)) != 0) | ||||
return (error); | return (error); | ||||
tv[0].tv_sec = ltv[0].tv_sec; | tv[0].tv_sec = ltv[0].tv_sec; | ||||
tv[0].tv_usec = ltv[0].tv_usec; | tv[0].tv_usec = ltv[0].tv_usec; | ||||
tv[1].tv_sec = ltv[1].tv_sec; | tv[1].tv_sec = ltv[1].tv_sec; | ||||
tv[1].tv_usec = ltv[1].tv_usec; | tv[1].tv_usec = ltv[1].tv_usec; | ||||
tvp = tv; | tvp = tv; | ||||
} | } | ||||
if (!LUSECONVPATH(td)) { | return (kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, | ||||
error = kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, | tvp, UIO_SYSSPACE)); | ||||
tvp, UIO_SYSSPACE); | |||||
} else { | |||||
LCONVPATHEXIST(args->fname, &fname); | |||||
error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, | |||||
tvp, UIO_SYSSPACE); | |||||
LFREEPATH(fname); | |||||
} | } | ||||
return (error); | |||||
} | |||||
#endif | #endif | ||||
static int | static int | ||||
linux_utimensat_lts_to_ts(struct l_timespec *l_times, struct timespec *times) | linux_utimensat_lts_to_ts(struct l_timespec *l_times, struct timespec *times) | ||||
{ | { | ||||
if (l_times->tv_nsec != LINUX_UTIME_OMIT && | if (l_times->tv_nsec != LINUX_UTIME_OMIT && | ||||
l_times->tv_nsec != LINUX_UTIME_NOW && | l_times->tv_nsec != LINUX_UTIME_NOW && | ||||
Show All 15 Lines | linux_utimensat_lts_to_ts(struct l_timespec *l_times, struct timespec *times) | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
linux_common_utimensat(struct thread *td, int ldfd, const char *pathname, | linux_common_utimensat(struct thread *td, int ldfd, const char *pathname, | ||||
struct timespec *timesp, int lflags) | struct timespec *timesp, int lflags) | ||||
{ | { | ||||
char *path = NULL; | int dfd, flags = 0; | ||||
int error, dfd, flags = 0; | |||||
dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd; | dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd; | ||||
if (lflags & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH)) | if (lflags & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH)) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (timesp != NULL) { | if (timesp != NULL) { | ||||
/* This breaks POSIX, but is what the Linux kernel does | /* This breaks POSIX, but is what the Linux kernel does | ||||
* _on purpose_ (documented in the man page for utimensat(2)), | * _on purpose_ (documented in the man page for utimensat(2)), | ||||
* so we must follow that behaviour. */ | * so we must follow that behaviour. */ | ||||
if (timesp[0].tv_nsec == UTIME_OMIT && | if (timesp[0].tv_nsec == UTIME_OMIT && | ||||
timesp[1].tv_nsec == UTIME_OMIT) | timesp[1].tv_nsec == UTIME_OMIT) | ||||
return (0); | return (0); | ||||
} | } | ||||
if (lflags & LINUX_AT_SYMLINK_NOFOLLOW) | if (lflags & LINUX_AT_SYMLINK_NOFOLLOW) | ||||
flags |= AT_SYMLINK_NOFOLLOW; | flags |= AT_SYMLINK_NOFOLLOW; | ||||
if (lflags & LINUX_AT_EMPTY_PATH) | if (lflags & LINUX_AT_EMPTY_PATH) | ||||
flags |= AT_EMPTY_PATH; | flags |= AT_EMPTY_PATH; | ||||
if (!LUSECONVPATH(td)) { | if (pathname != NULL) | ||||
if (pathname != NULL) { | |||||
return (kern_utimensat(td, dfd, pathname, | return (kern_utimensat(td, dfd, pathname, | ||||
UIO_USERSPACE, timesp, UIO_SYSSPACE, flags)); | UIO_USERSPACE, timesp, UIO_SYSSPACE, flags)); | ||||
} | |||||
} | |||||
if (pathname != NULL) | if (lflags != 0) | ||||
LCONVPATHEXIST_AT(pathname, &path, dfd); | |||||
else if (lflags != 0) | |||||
return (EINVAL); | return (EINVAL); | ||||
if (path == NULL) | return (kern_futimens(td, dfd, timesp, UIO_SYSSPACE)); | ||||
error = kern_futimens(td, dfd, timesp, UIO_SYSSPACE); | |||||
else { | |||||
error = kern_utimensat(td, dfd, path, UIO_SYSSPACE, timesp, | |||||
UIO_SYSSPACE, flags); | |||||
LFREEPATH(path); | |||||
} | } | ||||
return (error); | |||||
} | |||||
int | int | ||||
linux_utimensat(struct thread *td, struct linux_utimensat_args *args) | linux_utimensat(struct thread *td, struct linux_utimensat_args *args) | ||||
{ | { | ||||
struct l_timespec l_times[2]; | struct l_timespec l_times[2]; | ||||
struct timespec times[2], *timesp; | struct timespec times[2], *timesp; | ||||
int error; | int error; | ||||
if (args->times != NULL) { | if (args->times != NULL) { | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ | #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ | ||||
#ifdef LINUX_LEGACY_SYSCALLS | #ifdef LINUX_LEGACY_SYSCALLS | ||||
int | int | ||||
linux_futimesat(struct thread *td, struct linux_futimesat_args *args) | linux_futimesat(struct thread *td, struct linux_futimesat_args *args) | ||||
{ | { | ||||
l_timeval ltv[2]; | l_timeval ltv[2]; | ||||
struct timeval tv[2], *tvp = NULL; | struct timeval tv[2], *tvp = NULL; | ||||
char *fname; | |||||
int error, dfd; | int error, dfd; | ||||
dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; | dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; | ||||
if (args->utimes != NULL) { | if (args->utimes != NULL) { | ||||
if ((error = copyin(args->utimes, ltv, sizeof ltv)) != 0) | if ((error = copyin(args->utimes, ltv, sizeof ltv)) != 0) | ||||
return (error); | return (error); | ||||
tv[0].tv_sec = ltv[0].tv_sec; | tv[0].tv_sec = ltv[0].tv_sec; | ||||
tv[0].tv_usec = ltv[0].tv_usec; | tv[0].tv_usec = ltv[0].tv_usec; | ||||
tv[1].tv_sec = ltv[1].tv_sec; | tv[1].tv_sec = ltv[1].tv_sec; | ||||
tv[1].tv_usec = ltv[1].tv_usec; | tv[1].tv_usec = ltv[1].tv_usec; | ||||
tvp = tv; | tvp = tv; | ||||
} | } | ||||
if (!LUSECONVPATH(td)) { | return (kern_utimesat(td, dfd, args->filename, UIO_USERSPACE, | ||||
error = kern_utimesat(td, dfd, args->filename, UIO_USERSPACE, | tvp, UIO_SYSSPACE)); | ||||
tvp, UIO_SYSSPACE); | |||||
} else { | |||||
LCONVPATHEXIST_AT(args->filename, &fname, dfd); | |||||
error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, | |||||
tvp, UIO_SYSSPACE); | |||||
LFREEPATH(fname); | |||||
} | } | ||||
return (error); | |||||
} | |||||
#endif | #endif | ||||
static int | static int | ||||
linux_common_wait(struct thread *td, idtype_t idtype, int id, int *statusp, | linux_common_wait(struct thread *td, idtype_t idtype, int id, int *statusp, | ||||
int options, void *rup, l_siginfo_t *infop) | int options, void *rup, l_siginfo_t *infop) | ||||
{ | { | ||||
l_siginfo_t lsi; | l_siginfo_t lsi; | ||||
siginfo_t siginfo; | siginfo_t siginfo; | ||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | linux_waitid(struct thread *td, struct linux_waitid_args *args) | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef LINUX_LEGACY_SYSCALLS | #ifdef LINUX_LEGACY_SYSCALLS | ||||
int | int | ||||
linux_mknod(struct thread *td, struct linux_mknod_args *args) | linux_mknod(struct thread *td, struct linux_mknod_args *args) | ||||
{ | { | ||||
char *path; | |||||
int error; | int error; | ||||
enum uio_seg seg; | |||||
bool convpath; | |||||
convpath = LUSECONVPATH(td); | |||||
if (!convpath) { | |||||
path = args->path; | |||||
seg = UIO_USERSPACE; | |||||
} else { | |||||
LCONVPATHCREAT(args->path, &path); | |||||
seg = UIO_SYSSPACE; | |||||
} | |||||
switch (args->mode & S_IFMT) { | switch (args->mode & S_IFMT) { | ||||
case S_IFIFO: | case S_IFIFO: | ||||
case S_IFSOCK: | case S_IFSOCK: | ||||
error = kern_mkfifoat(td, AT_FDCWD, path, seg, | error = kern_mkfifoat(td, AT_FDCWD, args->path, UIO_USERSPACE, | ||||
args->mode); | args->mode); | ||||
break; | break; | ||||
case S_IFCHR: | case S_IFCHR: | ||||
case S_IFBLK: | case S_IFBLK: | ||||
error = kern_mknodat(td, AT_FDCWD, path, seg, | error = kern_mknodat(td, AT_FDCWD, args->path, UIO_USERSPACE, | ||||
args->mode, linux_decode_dev(args->dev)); | args->mode, linux_decode_dev(args->dev)); | ||||
break; | break; | ||||
case S_IFDIR: | case S_IFDIR: | ||||
error = EPERM; | error = EPERM; | ||||
break; | break; | ||||
case 0: | case 0: | ||||
args->mode |= S_IFREG; | args->mode |= S_IFREG; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case S_IFREG: | case S_IFREG: | ||||
error = kern_openat(td, AT_FDCWD, path, seg, | error = kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE, | ||||
O_WRONLY | O_CREAT | O_TRUNC, args->mode); | O_WRONLY | O_CREAT | O_TRUNC, args->mode); | ||||
if (error == 0) | if (error == 0) | ||||
kern_close(td, td->td_retval[0]); | kern_close(td, td->td_retval[0]); | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
if (convpath) | |||||
LFREEPATH(path); | |||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif | ||||
int | int | ||||
linux_mknodat(struct thread *td, struct linux_mknodat_args *args) | linux_mknodat(struct thread *td, struct linux_mknodat_args *args) | ||||
{ | { | ||||
char *path; | |||||
int error, dfd; | int error, dfd; | ||||
enum uio_seg seg; | |||||
bool convpath; | |||||
dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; | dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; | ||||
convpath = LUSECONVPATH(td); | |||||
if (!convpath) { | |||||
path = __DECONST(char *, args->filename); | |||||
seg = UIO_USERSPACE; | |||||
} else { | |||||
LCONVPATHCREAT_AT(args->filename, &path, dfd); | |||||
seg = UIO_SYSSPACE; | |||||
} | |||||
switch (args->mode & S_IFMT) { | switch (args->mode & S_IFMT) { | ||||
case S_IFIFO: | case S_IFIFO: | ||||
case S_IFSOCK: | case S_IFSOCK: | ||||
error = kern_mkfifoat(td, dfd, path, seg, args->mode); | error = kern_mkfifoat(td, dfd, args->filename, UIO_USERSPACE, | ||||
args->mode); | |||||
break; | break; | ||||
case S_IFCHR: | case S_IFCHR: | ||||
case S_IFBLK: | case S_IFBLK: | ||||
error = kern_mknodat(td, dfd, path, seg, args->mode, | error = kern_mknodat(td, dfd, args->filename, UIO_USERSPACE, | ||||
linux_decode_dev(args->dev)); | args->mode, linux_decode_dev(args->dev)); | ||||
break; | break; | ||||
case S_IFDIR: | case S_IFDIR: | ||||
error = EPERM; | error = EPERM; | ||||
break; | break; | ||||
case 0: | case 0: | ||||
args->mode |= S_IFREG; | args->mode |= S_IFREG; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case S_IFREG: | case S_IFREG: | ||||
error = kern_openat(td, dfd, path, seg, | error = kern_openat(td, dfd, args->filename, UIO_USERSPACE, | ||||
O_WRONLY | O_CREAT | O_TRUNC, args->mode); | O_WRONLY | O_CREAT | O_TRUNC, args->mode); | ||||
if (error == 0) | if (error == 0) | ||||
kern_close(td, td->td_retval[0]); | kern_close(td, td->td_retval[0]); | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
if (convpath) | |||||
LFREEPATH(path); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* UGH! This is just about the dumbest idea I've ever heard!! | * UGH! This is just about the dumbest idea I've ever heard!! | ||||
*/ | */ | ||||
int | int | ||||
linux_personality(struct thread *td, struct linux_personality_args *args) | linux_personality(struct thread *td, struct linux_personality_args *args) | ||||
▲ Show 20 Lines • Show All 1,633 Lines • ▼ Show 20 Lines | linux_seccomp(struct thread *td, struct linux_seccomp_args *args) | ||||
} | } | ||||
} | } | ||||
#ifndef COMPAT_LINUX32 | #ifndef COMPAT_LINUX32 | ||||
int | int | ||||
linux_execve(struct thread *td, struct linux_execve_args *args) | linux_execve(struct thread *td, struct linux_execve_args *args) | ||||
{ | { | ||||
struct image_args eargs; | struct image_args eargs; | ||||
char *path; | |||||
int error; | int error; | ||||
LINUX_CTR(execve); | LINUX_CTR(execve); | ||||
if (!LUSECONVPATH(td)) { | |||||
error = exec_copyin_args(&eargs, args->path, UIO_USERSPACE, | error = exec_copyin_args(&eargs, args->path, UIO_USERSPACE, | ||||
args->argp, args->envp); | args->argp, args->envp); | ||||
} else { | |||||
LCONVPATHEXIST(args->path, &path); | |||||
error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp, | |||||
args->envp); | |||||
LFREEPATH(path); | |||||
} | |||||
if (error == 0) | if (error == 0) | ||||
error = linux_common_execve(td, &eargs); | error = linux_common_execve(td, &eargs); | ||||
AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td); | AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif |