diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-06-30 00:21:34 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-06-30 00:21:34 +0000 |
commit | 3917ac5846dd0f9ad1238166f90caab9912052e6 (patch) | |
tree | 1c298935def4f29edb39192365a65d73de999155 /kernel | |
parent | af2f803c8b2d469fe38e4a7ce952658dfcb6681a (diff) |
o Merge with Linux 2.1.100.
o Cleanup the machine dependencies of floppy and rtc. The driver for
the Dallas thingy in the Indy is still missing.
o Handle allocation of zero'd pages correct for R4000SC / R4400SC.
o Page colouring shit to match the virtual and physical colour of all
mapped pages. This tends to produce extreme fragmentation problems,
so it's deactivated for now. Users of R4000SC / R4400SC may re-enable
the code in arch/mips/mm/init.c by removing the definition of
CONF_GIVE_A_SHIT_ABOUT_COLOURS. Should get them somewhat further -
but don't shake to hard ...
o Fixed ptrace(2)-ing of syscalls, strace is now working again.
o Fix the interrupt forwarding from the keyboard driver to the psaux
driver, PS/2 mice are now working on the Indy. The fix is somewhat
broken as it prevents generic kernels for Indy and machines which handle
things different.
o Things I can't remember.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/acct.c | 2 | ||||
-rw-r--r-- | kernel/capability.c | 252 | ||||
-rw-r--r-- | kernel/fork.c | 8 | ||||
-rw-r--r-- | kernel/module.c | 6 | ||||
-rw-r--r-- | kernel/printk.c | 2 | ||||
-rw-r--r-- | kernel/sched.c | 7 | ||||
-rw-r--r-- | kernel/signal.c | 2 | ||||
-rw-r--r-- | kernel/sys.c | 113 | ||||
-rw-r--r-- | kernel/sysctl.c | 12 | ||||
-rw-r--r-- | kernel/time.c | 6 |
11 files changed, 371 insertions, 41 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 4e0a1d87d..abd520d44 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -13,7 +13,7 @@ O_TARGET := kernel.o O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ - sysctl.o acct.o + sysctl.o acct.o capability.o OX_OBJS += signal.o diff --git a/kernel/acct.c b/kernel/acct.c index 4229b9ebf..6a00f3571 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -119,7 +119,7 @@ asmlinkage int sys_acct(const char *name) int error = -EPERM; lock_kernel(); - if (!suser()) + if (!capable(CAP_SYS_PACCT)) goto out; if (name == (char *)NULL) { diff --git a/kernel/capability.c b/kernel/capability.c new file mode 100644 index 000000000..ddbfaa87b --- /dev/null +++ b/kernel/capability.c @@ -0,0 +1,252 @@ +/* + * linux/kernel/capability.c + * + * Copyright (C) 1997 Andrew Main <zefram@fysh.org> + * Integrated into 2.1.97+, Andrew G. Morgan <morgan@transmeta.com> + */ + +#include <linux/config.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/capability.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/string.h> + +#include <asm/uaccess.h> + +static inline void cap_fromuser(kernel_cap_t *k, __u32 *u) +{ + copy_from_user(k, u, sizeof(*k)); +} + + +static inline void cap_touser(__u32 *u, const kernel_cap_t *k) +{ + copy_to_user(u, k, sizeof(*k)); +} + +#ifdef __SMP__ +static spinlock_t task_capability_lock; +#endif + +/* + * For sys_getproccap() and sys_setproccap(), any of the three + * capability set pointers may be NULL -- indicating that that set is + * uninteresting and/or not to be changed. + */ + +asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t data) +{ + int error = -EINVAL, pid; + __u32 version; + struct task_struct *target; + + if (!access_ok(VERIFY_WRITE, &header->version, sizeof(*header))) { + /* not large enough for current header so indicate error */ + if (access_ok(VERIFY_WRITE, &header->version, + sizeof(header->version))) { + return error; + } + goto all_done; + } + + copy_from_user(&version, &header->version, sizeof(header->version)); + if (version != _LINUX_CAPABILITY_VERSION) { + /* if enough space for kernel version, write that */ + + all_done: + version = _LINUX_CAPABILITY_VERSION; + copy_to_user(&header->version, &version, + sizeof(header->version)); + return error; + } + + if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) { + return error; + } + + copy_from_user(&pid, &header->pid, sizeof(header->pid)); + if (pid < 0) { + return error; + } + + spin_lock(&task_capability_lock); + + if (pid && pid != current->pid) { + read_lock(&tasklist_lock); + target = find_task_by_pid(pid); /* identify target of query */ + if (!target) { + error = -ESRCH; + goto out; + } + } else { + target = current; + } + + cap_touser(&data->permitted, &target->cap_permitted); + cap_touser(&data->inheritable, &target->cap_inheritable); + cap_touser(&data->effective, &target->cap_effective); + + error = 0; + +out: + if (target != current) { + read_unlock(&tasklist_lock); + } + spin_unlock(&task_capability_lock); + return error; +} + +/* set capabilities for all processes in a given process group */ + +static void cap_set_pg(int pgrp, + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) +{ + struct task_struct *target; + + /* FIXME: do we need to have a write lock here..? */ + read_lock(&tasklist_lock); + for_each_task(target) { + if (target->pgrp != pgrp) + continue; + target->cap_effective = *effective; + target->cap_inheritable = *inheritable; + target->cap_permitted = *permitted; + } + read_unlock(&tasklist_lock); +} + +/* set capabilities for all processes other than 1 and self */ + +static void cap_set_all(kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) +{ + struct task_struct *target; + + /* FIXME: do we need to have a write lock here..? */ + read_lock(&tasklist_lock); + /* ALL means everyone other than self or 'init' */ + for_each_task(target) { + if (target == current || target->pid == 1) + continue; + target->cap_effective = *effective; + target->cap_inheritable = *inheritable; + target->cap_permitted = *permitted; + } + read_unlock(&tasklist_lock); +} + +/* + * The restrictions on setting capabilities are specified as: + * + * [pid is for the 'target' task. 'current' is the calling task.] + * + * I: any raised capabilities must be a subset of the (old current) Permitted + * P: any raised capabilities must be a subset of the (old current) permitted + * E: must be set to a subset of (new target) Permitted + */ + +asmlinkage int sys_capset(cap_user_header_t header, const cap_user_data_t data) +{ + kernel_cap_t inheritable, permitted, effective; + __u32 version; + struct task_struct *target; + int error = -EINVAL, pid; + + if (!access_ok(VERIFY_WRITE, &header->version, sizeof(*header))) { + /* not large enough for current header so indicate error */ + if (!access_ok(VERIFY_WRITE, &header->version, + sizeof(header->version))) { + return error; + } + goto all_done; + } + + copy_from_user(&version, &header->version, sizeof(header->version)); + if (version != _LINUX_CAPABILITY_VERSION) { + + all_done: + version = _LINUX_CAPABILITY_VERSION; + copy_to_user(&header->version, &version, + sizeof(header->version)); + return error; + } + + if (!access_ok(VERIFY_READ, data, sizeof(*data))) { + return error; + } + + /* may want to set other processes at some point -- for now demand 0 */ + copy_from_user(&pid, &header->pid, sizeof(pid)); + + error = -EPERM; + if (pid && !capable(CAP_SETPCAP)) + return error; + + spin_lock(&task_capability_lock); + + if (pid > 0 && pid != current->pid) { + read_lock(&tasklist_lock); + target = find_task_by_pid(pid); /* identify target of query */ + if (!target) { + error = -ESRCH; + goto out; + } + } else { + target = current; + } + + /* copy from userspace */ + cap_fromuser(&effective, &data->effective); + cap_fromuser(&inheritable, &data->inheritable); + cap_fromuser(&permitted, &data->permitted); + + /* verify restrictions on target's new Inheritable set */ + if (!cap_issubset(inheritable, + cap_combine(target->cap_inheritable, + current->cap_permitted))) { + goto out; + } + + /* verify restrictions on target's new Permitted set */ + if (!cap_issubset(permitted, + cap_combine(target->cap_permitted, + current->cap_permitted))) { + goto out; + } + + /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ + if (!cap_issubset(effective, permitted)) { + goto out; + } + + /* having verified that the proposed changes are legal, + we now put them into effect. */ + error = 0; + + if (pid < 0) { + if (pid == -1) /* all procs other than current and init */ + cap_set_all(&effective, &inheritable, &permitted); + + else /* all procs in process group */ + cap_set_pg(-pid, &effective, &inheritable, &permitted); + goto spin_out; + } else { + /* FIXME: do we need to have a write lock here..? */ + target->cap_effective = effective; + target->cap_inheritable = inheritable; + target->cap_permitted = permitted; + } + +out: + if (target != current) { + read_unlock(&tasklist_lock); + } +spin_out: + spin_unlock(&task_capability_lock); + return error; +} diff --git a/kernel/fork.c b/kernel/fork.c index 88199cae1..c29c52ece 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -56,9 +56,7 @@ static struct uid_taskcount { int task_count; } *uidhash[UIDHASH_SZ]; -#ifdef __SMP__ -static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; -#endif +spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; kmem_cache_t *uid_cachep; @@ -154,10 +152,8 @@ static inline int find_empty_process(void) return -EAGAIN; } -#ifdef __SMP__ /* Protects next_safe and last_pid. */ -static spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED; -#endif +spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED; static int get_pid(unsigned long flags) { diff --git a/kernel/module.c b/kernel/module.c index 90f0bf1a2..2d0665246 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -120,7 +120,7 @@ sys_create_module(const char *name_user, size_t size) struct module *mod; lock_kernel(); - if (!suser()) { + if (!capable(CAP_SYS_MODULE)) { error = -EPERM; goto err0; } @@ -175,7 +175,7 @@ sys_init_module(const char *name_user, struct module *mod_user) struct module_ref *dep; lock_kernel(); - if (!suser()) + if (!capable(CAP_SYS_MODULE)) goto err0; if ((namelen = get_mod_name(name_user, &name)) < 0) { error = namelen; @@ -366,7 +366,7 @@ sys_delete_module(const char *name_user) int something_changed; lock_kernel(); - if (!suser()) + if (!capable(CAP_SYS_MODULE)) goto out; if (name_user) { diff --git a/kernel/printk.c b/kernel/printk.c index 48922d779..9060da3ef 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -130,7 +130,7 @@ asmlinkage int sys_syslog(int type, char * buf, int len) int error = -EPERM; lock_kernel(); - if ((type != 3) && !suser()) + if ((type != 3) && !capable(CAP_SYS_ADMIN)) goto out; error = 0; switch (type) { diff --git a/kernel/sched.c b/kernel/sched.c index f9246e785..af68649ef 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1227,7 +1227,7 @@ asmlinkage int sys_nice(int increment) newprio = increment; if (increment < 0) { - if (!suser()) + if (!capable(CAP_SYS_NICE)) return -EPERM; newprio = -increment; increase = 1; @@ -1322,10 +1322,11 @@ static int setscheduler(pid_t pid, int policy, goto out_unlock; retval = -EPERM; - if ((policy == SCHED_FIFO || policy == SCHED_RR) && !suser()) + if ((policy == SCHED_FIFO || policy == SCHED_RR) && + !capable(CAP_SYS_NICE)) goto out_unlock; if ((current->euid != p->euid) && (current->euid != p->uid) && - !suser()) + !capable(CAP_SYS_NICE)) goto out_unlock; retval = 0; diff --git a/kernel/signal.c b/kernel/signal.c index f9145783e..c6a512c19 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -235,7 +235,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig); && ((sig != SIGCONT) || (current->session != t->session)) && (current->euid ^ t->suid) && (current->euid ^ t->uid) && (current->uid ^ t->suid) && (current->uid ^ t->uid) - && !suser()) + && !capable(CAP_SYS_ADMIN)) goto out_nolock; /* The null signal is a permissions and process existance probe. diff --git a/kernel/sys.c b/kernel/sys.c index aadb3ab5f..1de75c366 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -114,13 +114,13 @@ asmlinkage int sys_setpriority(int which, int who, int niceval) if (!proc_sel(p, which, who)) continue; if (p->uid != current->euid && - p->uid != current->uid && !suser()) { + p->uid != current->uid && !capable(CAP_SYS_NICE)) { error = EPERM; continue; } if (error == ESRCH) error = 0; - if (priority > p->priority && !suser()) + if (priority > p->priority && !capable(CAP_SYS_NICE)) error = EACCES; else p->priority = priority; @@ -172,7 +172,7 @@ asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg) char buffer[256]; /* We only trust the superuser with rebooting the system. */ - if (!suser()) + if (!capable(CAP_SYS_BOOT)) return -EPERM; /* For safety, we require "magic" arguments. */ @@ -273,7 +273,7 @@ asmlinkage int sys_setregid(gid_t rgid, gid_t egid) if (rgid != (gid_t) -1) { if ((old_rgid == rgid) || (current->egid==rgid) || - suser()) + capable(CAP_SETGID)) current->gid = rgid; else return -EPERM; @@ -282,7 +282,7 @@ asmlinkage int sys_setregid(gid_t rgid, gid_t egid) if ((old_rgid == egid) || (current->egid == egid) || (current->sgid == egid) || - suser()) + capable(CAP_SETGID)) current->fsgid = current->egid = egid; else { current->gid = old_rgid; @@ -307,7 +307,7 @@ asmlinkage int sys_setgid(gid_t gid) { int old_egid = current->egid; - if (suser()) + if (capable(CAP_SETGID)) current->gid = current->egid = current->sgid = current->fsgid = gid; else if ((gid == current->gid) || (gid == current->sgid)) current->egid = current->fsgid = gid; @@ -319,6 +319,41 @@ asmlinkage int sys_setgid(gid_t gid) return 0; } +/* + * cap_emulate_setxuid() fixes the effective / permitted capabilities of + * a process after a call to setuid, setreuid, or setresuid. + * + * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of + * {r,e,s}uid != 0, the permitted and effective capabilities are + * cleared. + * + * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective + * capabilities of the process are cleared. + * + * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective + * capabilities are set to the permitted capabilities. + * + * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should + * never happen. + * + * -astor + */ +extern inline void cap_emulate_setxuid(int old_ruid, int old_euid, + int old_suid) +{ + if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && + (current->uid != 0 && current->euid != 0 && current->suid != 0)) { + cap_clear(current->cap_permitted); + cap_clear(current->cap_effective); + } + if (old_euid == 0 && current->euid != 0) { + cap_clear(current->cap_effective); + } + if (old_euid != 0 && current->euid == 0) { + current->cap_effective = current->cap_permitted; + } +} + /* * Unprivileged users may change the real uid to the effective uid * or vice versa. (BSD-style) @@ -336,14 +371,15 @@ asmlinkage int sys_setgid(gid_t gid) */ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) { - int old_ruid, old_euid, new_ruid; + int old_ruid, old_euid, old_suid, new_ruid; new_ruid = old_ruid = current->uid; old_euid = current->euid; + old_suid = current->suid; if (ruid != (uid_t) -1) { if ((old_ruid == ruid) || (current->euid==ruid) || - suser()) + capable(CAP_SETUID)) new_ruid = ruid; else return -EPERM; @@ -352,7 +388,7 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) if ((old_ruid == euid) || (current->euid == euid) || (current->suid == euid) || - suser()) + capable(CAP_SETUID)) current->fsuid = current->euid = euid; else return -EPERM; @@ -375,9 +411,16 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) if(new_ruid) charge_uid(current, 1); } + + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + cap_emulate_setxuid(old_ruid, old_euid, old_suid); + } + return 0; } + + /* * setuid() is implemented like SysV w/ SAVED_IDS * @@ -392,10 +435,11 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) asmlinkage int sys_setuid(uid_t uid) { int old_euid = current->euid; - int old_ruid, new_ruid; + int old_ruid, old_suid, new_ruid; old_ruid = new_ruid = current->uid; - if (suser()) + old_suid = current->suid; + if (capable(CAP_SETUID)) new_ruid = current->euid = current->suid = current->fsuid = uid; else if ((uid == current->uid) || (uid == current->suid)) current->fsuid = current->euid = uid; @@ -412,6 +456,11 @@ asmlinkage int sys_setuid(uid_t uid) if(new_ruid) charge_uid(current, 1); } + + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + cap_emulate_setxuid(old_ruid, old_euid, old_suid); + } + return 0; } @@ -422,6 +471,9 @@ asmlinkage int sys_setuid(uid_t uid) */ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) { + int old_ruid = current->uid; + int old_euid = current->euid; + int old_suid = current->suid; if (current->uid != 0 && current->euid != 0 && current->suid != 0) { if ((ruid != (uid_t) -1) && (ruid != current->uid) && (ruid != current->euid) && (ruid != current->suid)) @@ -448,6 +500,11 @@ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) } if (suid != (uid_t) -1) current->suid = suid; + + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + cap_emulate_setxuid(old_ruid, old_euid, old_suid); + } + return 0; } @@ -515,11 +572,31 @@ asmlinkage int sys_setfsuid(uid_t uid) old_fsuid = current->fsuid; if (uid == current->uid || uid == current->euid || - uid == current->suid || uid == current->fsuid || suser()) + uid == current->suid || uid == current->fsuid || + capable(CAP_SETUID)) current->fsuid = uid; if (current->fsuid != old_fsuid) current->dumpable = 0; + /* We emulate fsuid by essentially doing a scaled-down version + * of what we did in setresuid and friends. However, we only + * operate on the fs-specific bits of the process' effective + * capabilities + * + * FIXME - is fsuser used for all CAP_FS_MASK capabilities? + * if not, we might be a bit too harsh here. + */ + + if (!issecure(SECURE_NO_SETUID_FIXUP)) { + if (old_fsuid == 0 && current->fsuid != 0) { + current->cap_effective.cap &= ~CAP_FS_MASK; + } + if (old_fsuid != 0 && current->fsuid == 0) { + current->cap_effective.cap |= + (current->cap_permitted.cap & CAP_FS_MASK); + } + } + return old_fsuid; } @@ -532,7 +609,8 @@ asmlinkage int sys_setfsgid(gid_t gid) old_fsgid = current->fsgid; if (gid == current->gid || gid == current->egid || - gid == current->sgid || gid == current->fsgid || suser()) + gid == current->sgid || gid == current->fsgid || + capable(CAP_SETGID)) current->fsgid = gid; if (current->fsgid != old_fsgid) current->dumpable = 0; @@ -716,7 +794,7 @@ asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist) asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist) { - if (!suser()) + if (!capable(CAP_SETGID)) return -EPERM; if ((unsigned) gidsetsize > NGROUPS) return -EINVAL; @@ -756,7 +834,7 @@ asmlinkage int sys_newuname(struct new_utsname * name) asmlinkage int sys_sethostname(char *name, int len) { - if (!suser()) + if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; @@ -787,7 +865,7 @@ asmlinkage int sys_gethostname(char *name, int len) */ asmlinkage int sys_setdomainname(char *name, int len) { - if (!suser()) + if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; @@ -820,7 +898,7 @@ asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim) old_rlim = current->rlim + resource; if (((new_rlim.rlim_cur > old_rlim->rlim_max) || (new_rlim.rlim_max > old_rlim->rlim_max)) && - !suser()) + !capable(CAP_SYS_RESOURCE)) return -EPERM; if (resource == RLIMIT_NOFILE) { if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) @@ -916,3 +994,4 @@ asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, } return error; } + diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 27616bfee..0865db07c 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -189,20 +189,22 @@ static ctl_table kern_table[] = { static ctl_table vm_table[] = { {VM_SWAPCTL, "swapctl", - &swap_control, sizeof(swap_control_t), 0600, NULL, &proc_dointvec}, + &swap_control, sizeof(swap_control_t), 0644, NULL, &proc_dointvec}, {VM_SWAPOUT, "swapout_interval", - &swapout_interval, sizeof(int), 0600, NULL, &proc_dointvec}, + &swapout_interval, sizeof(int), 0644, NULL, &proc_dointvec}, {VM_FREEPG, "freepages", - &freepages, sizeof(freepages_t), 0600, NULL, &proc_dointvec}, + &freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec}, {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &bdflush_min, &bdflush_max}, {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory, sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec}, {VM_BUFFERMEM, "buffermem", - &buffer_mem, sizeof(buffer_mem_t), 0600, NULL, &proc_dointvec}, + &buffer_mem, sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec}, {VM_PAGECACHE, "pagecache", - &page_cache, sizeof(buffer_mem_t), 0600, NULL, &proc_dointvec}, + &page_cache, sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec}, + {VM_PAGERDAEMON, "kswapd", + &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec}, {0} }; diff --git a/kernel/time.c b/kernel/time.c index e16a7a150..ff3a5d684 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -87,7 +87,7 @@ asmlinkage int sys_stime(int * tptr) { int value; - if (!suser()) + if (!capable(CAP_SYS_TIME)) return -EPERM; if (get_user(value, tptr)) return -EFAULT; @@ -156,7 +156,7 @@ int do_sys_settimeofday(struct timeval *tv, struct timezone *tz) { static int firsttime = 1; - if (!suser()) + if (!capable(CAP_SYS_TIME)) return -EPERM; if (tz) { @@ -221,7 +221,7 @@ int do_adjtimex(struct timex *txc) long ltemp, mtemp, save_adjust; /* In order to modify anything, you gotta be super-user! */ - if (txc->modes && !suser()) + if (txc->modes && !capable(CAP_SYS_TIME)) return -EPERM; /* Now we validate the data before disabling interrupts */ |