Skip to content

Commit 4be9513

Browse files
committed
Merge branch 'work.sys_wait' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull wait syscall updates from Al Viro: "Consolidating sys_wait* and compat counterparts. Gets rid of set_fs()/double-copy mess, simplifies the whole thing (lifting the copyouts to the syscalls means less headache in the part that does actual work - fewer failure exits, to start with), gets rid of the overhead of field-by-field __put_user()" * 'work.sys_wait' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: osf_wait4: switch to kernel_wait4() waitid(): switch copyout of siginfo to unsafe_put_user() wait_task_zombie: consolidate info logics kill wait_noreap_copyout() lift getrusage() from wait_noreap_copyout() waitid(2): leave copyout of siginfo to syscall itself kernel_wait4()/kernel_waitid(): delay copying status to userland wait4(2)/waitid(2): separate copying rusage to userland move compat wait4 and waitid next to native variants
2 parents 3bad2f1 + 92ebce5 commit 4be9513

File tree

6 files changed

+187
-259
lines changed

6 files changed

+187
-259
lines changed

arch/alpha/kernel/osf_sys.c

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,48 +1183,23 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
11831183
SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
11841184
struct rusage32 __user *, ur)
11851185
{
1186-
struct rusage r;
1187-
long ret, err;
11881186
unsigned int status = 0;
1189-
mm_segment_t old_fs;
1190-
1187+
struct rusage r;
1188+
long err = kernel_wait4(pid, &status, options, &r);
1189+
if (err <= 0)
1190+
return err;
1191+
if (put_user(status, ustatus))
1192+
return -EFAULT;
11911193
if (!ur)
1192-
return sys_wait4(pid, ustatus, options, NULL);
1193-
1194-
old_fs = get_fs();
1195-
1196-
set_fs (KERNEL_DS);
1197-
ret = sys_wait4(pid, (unsigned int __user *) &status, options,
1198-
(struct rusage __user *) &r);
1199-
set_fs (old_fs);
1200-
1201-
if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
1194+
return err;
1195+
if (put_tv32(&ur->ru_utime, &r.ru_utime))
12021196
return -EFAULT;
1203-
1204-
err = put_user(status, ustatus);
1205-
if (ret < 0)
1206-
return err ? err : ret;
1207-
1208-
err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
1209-
err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
1210-
err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
1211-
err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
1212-
err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
1213-
err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
1214-
err |= __put_user(r.ru_idrss, &ur->ru_idrss);
1215-
err |= __put_user(r.ru_isrss, &ur->ru_isrss);
1216-
err |= __put_user(r.ru_minflt, &ur->ru_minflt);
1217-
err |= __put_user(r.ru_majflt, &ur->ru_majflt);
1218-
err |= __put_user(r.ru_nswap, &ur->ru_nswap);
1219-
err |= __put_user(r.ru_inblock, &ur->ru_inblock);
1220-
err |= __put_user(r.ru_oublock, &ur->ru_oublock);
1221-
err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
1222-
err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
1223-
err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
1224-
err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
1225-
err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
1226-
1227-
return err ? err : ret;
1197+
if (put_tv32(&ur->ru_stime, &r.ru_stime))
1198+
return -EFAULT;
1199+
if (copy_to_user(&ur->ru_maxrss, &r.ru_maxrss,
1200+
sizeof(struct rusage32) - offsetof(struct rusage32, ru_maxrss)))
1201+
return -EFAULT;
1202+
return err;
12281203
}
12291204

12301205
/*

include/linux/resource.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
struct task_struct;
88

9-
int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
9+
void getrusage(struct task_struct *p, int who, struct rusage *ru);
1010
int do_prlimit(struct task_struct *tsk, unsigned int resource,
1111
struct rlimit *new_rlim, struct rlimit *old_rlim);
1212

include/linux/sched/task.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/sched.h>
1010

1111
struct task_struct;
12+
struct rusage;
1213
union thread_union;
1314

1415
/*
@@ -74,6 +75,7 @@ extern long _do_fork(unsigned long, unsigned long, unsigned long, int __user *,
7475
extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
7576
struct task_struct *fork_idle(int);
7677
extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
78+
extern long kernel_wait4(pid_t, int *, int, struct rusage *);
7779

7880
extern void free_task(struct task_struct *tsk);
7981

kernel/compat.c

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -396,72 +396,6 @@ int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
396396
return 0;
397397
}
398398

399-
COMPAT_SYSCALL_DEFINE4(wait4,
400-
compat_pid_t, pid,
401-
compat_uint_t __user *, stat_addr,
402-
int, options,
403-
struct compat_rusage __user *, ru)
404-
{
405-
if (!ru) {
406-
return sys_wait4(pid, stat_addr, options, NULL);
407-
} else {
408-
struct rusage r;
409-
int ret;
410-
unsigned int status;
411-
mm_segment_t old_fs = get_fs();
412-
413-
set_fs (KERNEL_DS);
414-
ret = sys_wait4(pid,
415-
(stat_addr ?
416-
(unsigned int __user *) &status : NULL),
417-
options, (struct rusage __user *) &r);
418-
set_fs (old_fs);
419-
420-
if (ret > 0) {
421-
if (put_compat_rusage(&r, ru))
422-
return -EFAULT;
423-
if (stat_addr && put_user(status, stat_addr))
424-
return -EFAULT;
425-
}
426-
return ret;
427-
}
428-
}
429-
430-
COMPAT_SYSCALL_DEFINE5(waitid,
431-
int, which, compat_pid_t, pid,
432-
struct compat_siginfo __user *, uinfo, int, options,
433-
struct compat_rusage __user *, uru)
434-
{
435-
siginfo_t info;
436-
struct rusage ru;
437-
long ret;
438-
mm_segment_t old_fs = get_fs();
439-
440-
memset(&info, 0, sizeof(info));
441-
442-
set_fs(KERNEL_DS);
443-
ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
444-
uru ? (struct rusage __user *)&ru : NULL);
445-
set_fs(old_fs);
446-
447-
if ((ret < 0) || (info.si_signo == 0))
448-
return ret;
449-
450-
if (uru) {
451-
/* sys_waitid() overwrites everything in ru */
452-
if (COMPAT_USE_64BIT_TIME)
453-
ret = copy_to_user(uru, &ru, sizeof(ru));
454-
else
455-
ret = put_compat_rusage(&ru, uru);
456-
if (ret)
457-
return -EFAULT;
458-
}
459-
460-
BUG_ON(info.si_code & __SI_MASK);
461-
info.si_code |= __SI_CHLD;
462-
return copy_siginfo_to_user32(uinfo, &info);
463-
}
464-
465399
static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
466400
unsigned len, struct cpumask *new_mask)
467401
{

0 commit comments

Comments
 (0)