diff options
| author | David Howells <dhowells@redhat.com> | 2004-10-18 17:58:51 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-10-18 17:58:51 -0700 |
| commit | e4262f594a9e36cf93a8789fc7e02e9ff0d1f564 (patch) | |
| tree | f5265fb6090dc67eb231c3554b88320e9bfeeb26 /kernel | |
| parent | 322f317d1f560b90d8fe79d77fb248c98af92305 (diff) | |
[PATCH] implement in-kernel keys & keyring management
The feature set the patch includes:
- Key attributes:
- Key type
- Description (by which a key of a particular type can be selected)
- Payload
- UID, GID and permissions mask
- Expiry time
- Keyrings (just a type of key that holds links to other keys)
- User-defined keys
- Key revokation
- Access controls
- Per user key-count and key-memory consumption quota
- Three std keyrings per task: per-thread, per-process, session
- Two std keyrings per user: per-user and default-user-session
- prctl() functions for key and keyring creation and management
- Kernel interfaces for filesystem, blockdev, net stack access
- JIT key creation by usermode helper
There are also two utility programs available:
(*) http://people.redhat.com/~dhowells/keys/keyctl.c
A comprehensive key management tool, permitting all the interfaces
available to userspace to be exercised.
(*) http://people.redhat.com/~dhowells/keys/request-key
An example shell script (to be installed in /sbin) for instantiating a
key.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/exit.c | 2 | ||||
| -rw-r--r-- | kernel/fork.c | 13 | ||||
| -rw-r--r-- | kernel/sys.c | 20 | ||||
| -rw-r--r-- | kernel/user.c | 16 |
4 files changed, 47 insertions, 4 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 55d853392524..e242c22dee36 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -14,6 +14,7 @@ #include <linux/personality.h> #include <linux/tty.h> #include <linux/namespace.h> +#include <linux/key.h> #include <linux/security.h> #include <linux/cpu.h> #include <linux/acct.h> @@ -816,6 +817,7 @@ asmlinkage NORET_TYPE void do_exit(long code) __exit_fs(tsk); exit_namespace(tsk); exit_thread(); + exit_keys(tsk); if (tsk->signal->leader) disassociate_ctty(1); diff --git a/kernel/fork.c b/kernel/fork.c index 3020dccc548f..2502791f0ba4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -24,6 +24,7 @@ #include <linux/mempolicy.h> #include <linux/sem.h> #include <linux/file.h> +#include <linux/key.h> #include <linux/binfmts.h> #include <linux/mman.h> #include <linux/fs.h> @@ -1019,6 +1020,10 @@ static task_t *copy_process(unsigned long clone_flags, } #endif + p->tgid = p->pid; + if (clone_flags & CLONE_THREAD) + p->tgid = current->tgid; + if ((retval = security_task_alloc(p))) goto bad_fork_cleanup_policy; if ((retval = audit_alloc(p))) @@ -1036,8 +1041,10 @@ static task_t *copy_process(unsigned long clone_flags, goto bad_fork_cleanup_sighand; if ((retval = copy_mm(clone_flags, p))) goto bad_fork_cleanup_signal; - if ((retval = copy_namespace(clone_flags, p))) + if ((retval = copy_keys(clone_flags, p))) goto bad_fork_cleanup_mm; + if ((retval = copy_namespace(clone_flags, p))) + goto bad_fork_cleanup_keys; retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) goto bad_fork_cleanup_namespace; @@ -1071,7 +1078,6 @@ static task_t *copy_process(unsigned long clone_flags, * Ok, make it visible to the rest of the system. * We dont wake it up yet. */ - p->tgid = p->pid; p->group_leader = p; INIT_LIST_HEAD(&p->ptrace_children); INIT_LIST_HEAD(&p->ptrace_list); @@ -1119,7 +1125,6 @@ static task_t *copy_process(unsigned long clone_flags, retval = -EAGAIN; goto bad_fork_cleanup_namespace; } - p->tgid = current->tgid; p->group_leader = current->group_leader; if (current->signal->group_stop_count > 0) { @@ -1159,6 +1164,8 @@ fork_out: bad_fork_cleanup_namespace: exit_namespace(p); +bad_fork_cleanup_keys: + exit_keys(p); bad_fork_cleanup_mm: if (p->mm) mmput(p->mm); diff --git a/kernel/sys.c b/kernel/sys.c index a95e3900dc1e..e6dbc2940751 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -19,6 +19,7 @@ #include <linux/fs.h> #include <linux/workqueue.h> #include <linux/device.h> +#include <linux/key.h> #include <linux/times.h> #include <linux/security.h> #include <linux/dcookies.h> @@ -282,6 +283,9 @@ cond_syscall(sys_set_mempolicy) cond_syscall(compat_mbind) cond_syscall(compat_get_mempolicy) cond_syscall(compat_set_mempolicy) +cond_syscall(sys_add_key) +cond_syscall(sys_request_key) +cond_syscall(sys_keyctl) /* arch-specific weak syscall entries */ cond_syscall(sys_pciconfig_read) @@ -605,6 +609,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) current->fsgid = new_egid; current->egid = new_egid; current->gid = new_rgid; + key_fsgid_changed(current); return 0; } @@ -642,6 +647,8 @@ asmlinkage long sys_setgid(gid_t gid) } else return -EPERM; + + key_fsgid_changed(current); return 0; } @@ -730,6 +737,8 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) current->suid = current->euid; current->fsuid = current->euid; + key_fsuid_changed(current); + return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); } @@ -775,6 +784,8 @@ asmlinkage long sys_setuid(uid_t uid) current->fsuid = current->euid = uid; current->suid = new_suid; + key_fsuid_changed(current); + return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); } @@ -821,6 +832,8 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) if (suid != (uid_t) -1) current->suid = suid; + key_fsuid_changed(current); + return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); } @@ -870,6 +883,8 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) current->gid = rgid; if (sgid != (gid_t) -1) current->sgid = sgid; + + key_fsgid_changed(current); return 0; } @@ -911,6 +926,8 @@ asmlinkage long sys_setfsuid(uid_t uid) current->fsuid = uid; } + key_fsuid_changed(current); + security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS); return old_fsuid; @@ -937,6 +954,7 @@ asmlinkage long sys_setfsgid(gid_t gid) wmb(); } current->fsgid = gid; + key_fsgid_changed(current); } return old_fsgid; } @@ -1669,7 +1687,7 @@ asmlinkage long sys_umask(int mask) asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { - int error; + long error; int sig; error = security_task_prctl(option, arg2, arg3, arg4, arg5); diff --git a/kernel/user.c b/kernel/user.c index 523175afeecd..693487dc940e 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -12,6 +12,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/bitops.h> +#include <linux/key.h> /* * UID task count cache, to get fast user lookup in "alloc_uid" @@ -34,6 +35,10 @@ struct user_struct root_user = { .sigpending = ATOMIC_INIT(0), .mq_bytes = 0, .locked_shm = 0, +#ifdef CONFIG_KEYS + .uid_keyring = &root_user_keyring, + .session_keyring = &root_session_keyring, +#endif }; /* @@ -87,6 +92,8 @@ void free_uid(struct user_struct *up) { if (up && atomic_dec_and_lock(&up->__count, &uidhash_lock)) { uid_hash_remove(up); + key_put(up->uid_keyring); + key_put(up->session_keyring); kmem_cache_free(uid_cachep, up); spin_unlock(&uidhash_lock); } @@ -116,6 +123,11 @@ struct user_struct * alloc_uid(uid_t uid) new->mq_bytes = 0; new->locked_shm = 0; + if (alloc_uid_keyring(new) < 0) { + kmem_cache_free(uid_cachep, new); + return NULL; + } + /* * Before adding this, check whether we raced * on adding the same user already.. @@ -123,6 +135,8 @@ struct user_struct * alloc_uid(uid_t uid) spin_lock(&uidhash_lock); up = uid_hash_find(uid, hashent); if (up) { + key_put(new->uid_keyring); + key_put(new->session_keyring); kmem_cache_free(uid_cachep, new); } else { uid_hash_insert(new, hashent); @@ -146,8 +160,10 @@ void switch_uid(struct user_struct *new_user) old_user = current->user; atomic_inc(&new_user->processes); atomic_dec(&old_user->processes); + switch_uid_keyring(new_user); current->user = new_user; free_uid(old_user); + suid_keys(current); } |
