summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
commit3917ac5846dd0f9ad1238166f90caab9912052e6 (patch)
tree1c298935def4f29edb39192365a65d73de999155 /kernel
parentaf2f803c8b2d469fe38e4a7ce952658dfcb6681a (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/Makefile2
-rw-r--r--kernel/acct.c2
-rw-r--r--kernel/capability.c252
-rw-r--r--kernel/fork.c8
-rw-r--r--kernel/module.c6
-rw-r--r--kernel/printk.c2
-rw-r--r--kernel/sched.c7
-rw-r--r--kernel/signal.c2
-rw-r--r--kernel/sys.c113
-rw-r--r--kernel/sysctl.c12
-rw-r--r--kernel/time.c6
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 */