diff options
| author | Iulia Manda <iulia.manda21@gmail.com> | 2015-04-15 19:16:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-15 19:35:22 -0400 |
| commit | 2813893f8b197a14f1e1ddb04d99bce46817c84a (patch) | |
| tree | 650651e638f867a6bda23e08c70bdd9857d121ca /kernel | |
| parent | c79574abe2baddf569532e7e430e4977771dd25c (diff) | |
kernel: conditionally support non-root users, groups and capabilities
There are a lot of embedded systems that run most or all of their
functionality in init, running as root:root. For these systems,
supporting multiple users is not necessary.
This patch adds a new symbol, CONFIG_MULTIUSER, that makes support for
non-root users, non-root groups, and capabilities optional. It is enabled
under CONFIG_EXPERT menu.
When this symbol is not defined, UID and GID are zero in any possible case
and processes always have all capabilities.
The following syscalls are compiled out: setuid, setregid, setgid,
setreuid, setresuid, getresuid, setresgid, getresgid, setgroups,
getgroups, setfsuid, setfsgid, capget, capset.
Also, groups.c is compiled out completely.
In kernel/capability.c, capable function was moved in order to avoid
adding two ifdef blocks.
This change saves about 25 KB on a defconfig build. The most minimal
kernels have total text sizes in the high hundreds of kB rather than
low MB. (The 25k goes down a bit with allnoconfig, but not that much.
The kernel was booted in Qemu. All the common functionalities work.
Adding users/groups is not possible, failing with -ENOSYS.
Bloat-o-meter output:
add/remove: 7/87 grow/shrink: 19/397 up/down: 1675/-26325 (-24650)
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Iulia Manda <iulia.manda21@gmail.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Tested-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/Makefile | 4 | ||||
| -rw-r--r-- | kernel/capability.c | 35 | ||||
| -rw-r--r-- | kernel/cred.c | 3 | ||||
| -rw-r--r-- | kernel/groups.c | 3 | ||||
| -rw-r--r-- | kernel/sys.c | 2 | ||||
| -rw-r--r-- | kernel/sys_ni.c | 14 |
6 files changed, 41 insertions, 20 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 1408b3353a3c..0f8f8b0bc1bf 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -9,7 +9,9 @@ obj-y = fork.o exec_domain.o panic.o \ | |||
| 9 | extable.o params.o \ | 9 | extable.o params.o \ |
| 10 | kthread.o sys_ni.o nsproxy.o \ | 10 | kthread.o sys_ni.o nsproxy.o \ |
| 11 | notifier.o ksysfs.o cred.o reboot.o \ | 11 | notifier.o ksysfs.o cred.o reboot.o \ |
| 12 | async.o range.o groups.o smpboot.o | 12 | async.o range.o smpboot.o |
| 13 | |||
| 14 | obj-$(CONFIG_MULTIUSER) += groups.o | ||
| 13 | 15 | ||
| 14 | ifdef CONFIG_FUNCTION_TRACER | 16 | ifdef CONFIG_FUNCTION_TRACER |
| 15 | # Do not trace debug files and internal ftrace files | 17 | # Do not trace debug files and internal ftrace files |
diff --git a/kernel/capability.c b/kernel/capability.c index 989f5bfc57dc..45432b54d5c6 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
| @@ -35,6 +35,7 @@ static int __init file_caps_disable(char *str) | |||
| 35 | } | 35 | } |
| 36 | __setup("no_file_caps", file_caps_disable); | 36 | __setup("no_file_caps", file_caps_disable); |
| 37 | 37 | ||
| 38 | #ifdef CONFIG_MULTIUSER | ||
| 38 | /* | 39 | /* |
| 39 | * More recent versions of libcap are available from: | 40 | * More recent versions of libcap are available from: |
| 40 | * | 41 | * |
| @@ -386,6 +387,24 @@ bool ns_capable(struct user_namespace *ns, int cap) | |||
| 386 | } | 387 | } |
| 387 | EXPORT_SYMBOL(ns_capable); | 388 | EXPORT_SYMBOL(ns_capable); |
| 388 | 389 | ||
| 390 | |||
| 391 | /** | ||
| 392 | * capable - Determine if the current task has a superior capability in effect | ||
| 393 | * @cap: The capability to be tested for | ||
| 394 | * | ||
| 395 | * Return true if the current task has the given superior capability currently | ||
| 396 | * available for use, false if not. | ||
| 397 | * | ||
| 398 | * This sets PF_SUPERPRIV on the task if the capability is available on the | ||
| 399 | * assumption that it's about to be used. | ||
| 400 | */ | ||
| 401 | bool capable(int cap) | ||
| 402 | { | ||
| 403 | return ns_capable(&init_user_ns, cap); | ||
| 404 | } | ||
| 405 | EXPORT_SYMBOL(capable); | ||
| 406 | #endif /* CONFIG_MULTIUSER */ | ||
| 407 | |||
| 389 | /** | 408 | /** |
| 390 | * file_ns_capable - Determine if the file's opener had a capability in effect | 409 | * file_ns_capable - Determine if the file's opener had a capability in effect |
| 391 | * @file: The file we want to check | 410 | * @file: The file we want to check |
| @@ -412,22 +431,6 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns, | |||
| 412 | EXPORT_SYMBOL(file_ns_capable); | 431 | EXPORT_SYMBOL(file_ns_capable); |
| 413 | 432 | ||
| 414 | /** | 433 | /** |
| 415 | * capable - Determine if the current task has a superior capability in effect | ||
| 416 | * @cap: The capability to be tested for | ||
| 417 | * | ||
| 418 | * Return true if the current task has the given superior capability currently | ||
| 419 | * available for use, false if not. | ||
| 420 | * | ||
| 421 | * This sets PF_SUPERPRIV on the task if the capability is available on the | ||
| 422 | * assumption that it's about to be used. | ||
| 423 | */ | ||
| 424 | bool capable(int cap) | ||
| 425 | { | ||
| 426 | return ns_capable(&init_user_ns, cap); | ||
| 427 | } | ||
| 428 | EXPORT_SYMBOL(capable); | ||
| 429 | |||
| 430 | /** | ||
| 431 | * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped | 434 | * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped |
| 432 | * @inode: The inode in question | 435 | * @inode: The inode in question |
| 433 | * @cap: The capability in question | 436 | * @cap: The capability in question |
diff --git a/kernel/cred.c b/kernel/cred.c index e0573a43c7df..ec1c07667ec1 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
| @@ -29,6 +29,9 @@ | |||
| 29 | 29 | ||
| 30 | static struct kmem_cache *cred_jar; | 30 | static struct kmem_cache *cred_jar; |
| 31 | 31 | ||
| 32 | /* init to 2 - one for init_task, one to ensure it is never freed */ | ||
| 33 | struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; | ||
| 34 | |||
| 32 | /* | 35 | /* |
| 33 | * The initial credentials for the initial task | 36 | * The initial credentials for the initial task |
| 34 | */ | 37 | */ |
diff --git a/kernel/groups.c b/kernel/groups.c index 664411f171b5..74d431d25251 100644 --- a/kernel/groups.c +++ b/kernel/groups.c | |||
| @@ -9,9 +9,6 @@ | |||
| 9 | #include <linux/user_namespace.h> | 9 | #include <linux/user_namespace.h> |
| 10 | #include <asm/uaccess.h> | 10 | #include <asm/uaccess.h> |
| 11 | 11 | ||
| 12 | /* init to 2 - one for init_task, one to ensure it is never freed */ | ||
| 13 | struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; | ||
| 14 | |||
| 15 | struct group_info *groups_alloc(int gidsetsize) | 12 | struct group_info *groups_alloc(int gidsetsize) |
| 16 | { | 13 | { |
| 17 | struct group_info *group_info; | 14 | struct group_info *group_info; |
diff --git a/kernel/sys.c b/kernel/sys.c index a03d9cd23ed7..3be344902316 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -325,6 +325,7 @@ out_unlock: | |||
| 325 | * SMP: There are not races, the GIDs are checked only by filesystem | 325 | * SMP: There are not races, the GIDs are checked only by filesystem |
| 326 | * operations (as far as semantic preservation is concerned). | 326 | * operations (as far as semantic preservation is concerned). |
| 327 | */ | 327 | */ |
| 328 | #ifdef CONFIG_MULTIUSER | ||
| 328 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | 329 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) |
| 329 | { | 330 | { |
| 330 | struct user_namespace *ns = current_user_ns(); | 331 | struct user_namespace *ns = current_user_ns(); |
| @@ -815,6 +816,7 @@ change_okay: | |||
| 815 | commit_creds(new); | 816 | commit_creds(new); |
| 816 | return old_fsgid; | 817 | return old_fsgid; |
| 817 | } | 818 | } |
| 819 | #endif /* CONFIG_MULTIUSER */ | ||
| 818 | 820 | ||
| 819 | /** | 821 | /** |
| 820 | * sys_getpid - return the thread group id of the current process | 822 | * sys_getpid - return the thread group id of the current process |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 5adcb0ae3a58..7995ef5868d8 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -159,6 +159,20 @@ cond_syscall(sys_uselib); | |||
| 159 | cond_syscall(sys_fadvise64); | 159 | cond_syscall(sys_fadvise64); |
| 160 | cond_syscall(sys_fadvise64_64); | 160 | cond_syscall(sys_fadvise64_64); |
| 161 | cond_syscall(sys_madvise); | 161 | cond_syscall(sys_madvise); |
| 162 | cond_syscall(sys_setuid); | ||
| 163 | cond_syscall(sys_setregid); | ||
| 164 | cond_syscall(sys_setgid); | ||
| 165 | cond_syscall(sys_setreuid); | ||
| 166 | cond_syscall(sys_setresuid); | ||
| 167 | cond_syscall(sys_getresuid); | ||
| 168 | cond_syscall(sys_setresgid); | ||
| 169 | cond_syscall(sys_getresgid); | ||
| 170 | cond_syscall(sys_setgroups); | ||
| 171 | cond_syscall(sys_getgroups); | ||
| 172 | cond_syscall(sys_setfsuid); | ||
| 173 | cond_syscall(sys_setfsgid); | ||
| 174 | cond_syscall(sys_capget); | ||
| 175 | cond_syscall(sys_capset); | ||
| 162 | 176 | ||
| 163 | /* arch-specific weak syscall entries */ | 177 | /* arch-specific weak syscall entries */ |
| 164 | cond_syscall(sys_pciconfig_read); | 178 | cond_syscall(sys_pciconfig_read); |
