diff options
-rw-r--r-- | include/linux/cred.h | 29 | ||||
-rw-r--r-- | include/linux/init_task.h | 16 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | include/linux/security.h | 26 | ||||
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/cred.c | 96 | ||||
-rw-r--r-- | kernel/fork.c | 24 | ||||
-rw-r--r-- | security/capability.c | 8 | ||||
-rw-r--r-- | security/security.c | 8 | ||||
-rw-r--r-- | security/selinux/hooks.c | 32 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 20 |
11 files changed, 179 insertions, 83 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h index 3e65587a72e5..a7a686074cb0 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
@@ -158,4 +158,33 @@ do { \ | |||
158 | *(_gid) = current->cred->fsgid; \ | 158 | *(_gid) = current->cred->fsgid; \ |
159 | } while(0) | 159 | } while(0) |
160 | 160 | ||
161 | extern void __put_cred(struct cred *); | ||
162 | extern int copy_creds(struct task_struct *, unsigned long); | ||
163 | |||
164 | /** | ||
165 | * get_cred - Get a reference on a set of credentials | ||
166 | * @cred: The credentials to reference | ||
167 | * | ||
168 | * Get a reference on the specified set of credentials. The caller must | ||
169 | * release the reference. | ||
170 | */ | ||
171 | static inline struct cred *get_cred(struct cred *cred) | ||
172 | { | ||
173 | atomic_inc(&cred->usage); | ||
174 | return cred; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * put_cred - Release a reference to a set of credentials | ||
179 | * @cred: The credentials to release | ||
180 | * | ||
181 | * Release a reference to a set of credentials, deleting them when the last ref | ||
182 | * is released. | ||
183 | */ | ||
184 | static inline void put_cred(struct cred *cred) | ||
185 | { | ||
186 | if (atomic_dec_and_test(&(cred)->usage)) | ||
187 | __put_cred(cred); | ||
188 | } | ||
189 | |||
161 | #endif /* _LINUX_CRED_H */ | 190 | #endif /* _LINUX_CRED_H */ |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 9de41ccd67b5..5e24c54b6dfd 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -115,19 +115,6 @@ extern struct group_info init_groups; | |||
115 | 115 | ||
116 | extern struct cred init_cred; | 116 | extern struct cred init_cred; |
117 | 117 | ||
118 | #define INIT_CRED(p) \ | ||
119 | { \ | ||
120 | .usage = ATOMIC_INIT(3), \ | ||
121 | .securebits = SECUREBITS_DEFAULT, \ | ||
122 | .cap_inheritable = CAP_INIT_INH_SET, \ | ||
123 | .cap_permitted = CAP_FULL_SET, \ | ||
124 | .cap_effective = CAP_INIT_EFF_SET, \ | ||
125 | .cap_bset = CAP_INIT_BSET, \ | ||
126 | .user = INIT_USER, \ | ||
127 | .group_info = &init_groups, \ | ||
128 | .lock = __SPIN_LOCK_UNLOCKED(p.lock), \ | ||
129 | } | ||
130 | |||
131 | /* | 118 | /* |
132 | * INIT_TASK is used to set up the first task table, touch at | 119 | * INIT_TASK is used to set up the first task table, touch at |
133 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 120 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
@@ -162,8 +149,7 @@ extern struct cred init_cred; | |||
162 | .children = LIST_HEAD_INIT(tsk.children), \ | 149 | .children = LIST_HEAD_INIT(tsk.children), \ |
163 | .sibling = LIST_HEAD_INIT(tsk.sibling), \ | 150 | .sibling = LIST_HEAD_INIT(tsk.sibling), \ |
164 | .group_leader = &tsk, \ | 151 | .group_leader = &tsk, \ |
165 | .__temp_cred = INIT_CRED(tsk.__temp_cred), \ | 152 | .cred = &init_cred, \ |
166 | .cred = &tsk.__temp_cred, \ | ||
167 | .comm = "swapper", \ | 153 | .comm = "swapper", \ |
168 | .thread = INIT_THREAD, \ | 154 | .thread = INIT_THREAD, \ |
169 | .fs = &init_fs, \ | 155 | .fs = &init_fs, \ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index c8b92502354d..740cf946c8cc 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1151,7 +1151,6 @@ struct task_struct { | |||
1151 | struct list_head cpu_timers[3]; | 1151 | struct list_head cpu_timers[3]; |
1152 | 1152 | ||
1153 | /* process credentials */ | 1153 | /* process credentials */ |
1154 | struct cred __temp_cred __deprecated; /* temporary credentials to be removed */ | ||
1155 | struct cred *cred; /* actual/objective task credentials */ | 1154 | struct cred *cred; /* actual/objective task credentials */ |
1156 | 1155 | ||
1157 | char comm[TASK_COMM_LEN]; /* executable name excluding path | 1156 | char comm[TASK_COMM_LEN]; /* executable name excluding path |
diff --git a/include/linux/security.h b/include/linux/security.h index 9f305d4a31a7..9239cc11eb9c 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -593,15 +593,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
593 | * manual page for definitions of the @clone_flags. | 593 | * manual page for definitions of the @clone_flags. |
594 | * @clone_flags contains the flags indicating what should be shared. | 594 | * @clone_flags contains the flags indicating what should be shared. |
595 | * Return 0 if permission is granted. | 595 | * Return 0 if permission is granted. |
596 | * @task_alloc_security: | 596 | * @cred_alloc_security: |
597 | * @p contains the task_struct for child process. | 597 | * @cred contains the cred struct for child process. |
598 | * Allocate and attach a security structure to the p->security field. The | 598 | * Allocate and attach a security structure to the cred->security field. |
599 | * security field is initialized to NULL when the task structure is | 599 | * The security field is initialized to NULL when the task structure is |
600 | * allocated. | 600 | * allocated. |
601 | * Return 0 if operation was successful. | 601 | * Return 0 if operation was successful. |
602 | * @task_free_security: | 602 | * @cred_free: |
603 | * @p contains the task_struct for process. | 603 | * @cred points to the credentials. |
604 | * Deallocate and clear the p->security field. | 604 | * Deallocate and clear the cred->security field in a set of credentials. |
605 | * @task_setuid: | 605 | * @task_setuid: |
606 | * Check permission before setting one or more of the user identity | 606 | * Check permission before setting one or more of the user identity |
607 | * attributes of the current process. The @flags parameter indicates | 607 | * attributes of the current process. The @flags parameter indicates |
@@ -1405,8 +1405,8 @@ struct security_operations { | |||
1405 | int (*dentry_open) (struct file *file); | 1405 | int (*dentry_open) (struct file *file); |
1406 | 1406 | ||
1407 | int (*task_create) (unsigned long clone_flags); | 1407 | int (*task_create) (unsigned long clone_flags); |
1408 | int (*task_alloc_security) (struct task_struct *p); | 1408 | int (*cred_alloc_security) (struct cred *cred); |
1409 | void (*task_free_security) (struct task_struct *p); | 1409 | void (*cred_free) (struct cred *cred); |
1410 | int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags); | 1410 | int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags); |
1411 | int (*task_post_setuid) (uid_t old_ruid /* or fsuid */ , | 1411 | int (*task_post_setuid) (uid_t old_ruid /* or fsuid */ , |
1412 | uid_t old_euid, uid_t old_suid, int flags); | 1412 | uid_t old_euid, uid_t old_suid, int flags); |
@@ -1660,8 +1660,8 @@ int security_file_send_sigiotask(struct task_struct *tsk, | |||
1660 | int security_file_receive(struct file *file); | 1660 | int security_file_receive(struct file *file); |
1661 | int security_dentry_open(struct file *file); | 1661 | int security_dentry_open(struct file *file); |
1662 | int security_task_create(unsigned long clone_flags); | 1662 | int security_task_create(unsigned long clone_flags); |
1663 | int security_task_alloc(struct task_struct *p); | 1663 | int security_cred_alloc(struct cred *cred); |
1664 | void security_task_free(struct task_struct *p); | 1664 | void security_cred_free(struct cred *cred); |
1665 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags); | 1665 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags); |
1666 | int security_task_post_setuid(uid_t old_ruid, uid_t old_euid, | 1666 | int security_task_post_setuid(uid_t old_ruid, uid_t old_euid, |
1667 | uid_t old_suid, int flags); | 1667 | uid_t old_suid, int flags); |
@@ -2181,12 +2181,12 @@ static inline int security_task_create(unsigned long clone_flags) | |||
2181 | return 0; | 2181 | return 0; |
2182 | } | 2182 | } |
2183 | 2183 | ||
2184 | static inline int security_task_alloc(struct task_struct *p) | 2184 | static inline int security_cred_alloc(struct cred *cred) |
2185 | { | 2185 | { |
2186 | return 0; | 2186 | return 0; |
2187 | } | 2187 | } |
2188 | 2188 | ||
2189 | static inline void security_task_free(struct task_struct *p) | 2189 | static inline void security_cred_free(struct cred *cred) |
2190 | { } | 2190 | { } |
2191 | 2191 | ||
2192 | static inline int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, | 2192 | static inline int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, |
diff --git a/kernel/Makefile b/kernel/Makefile index 9a3ec66a9d84..5a6a612c302d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -9,7 +9,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ | |||
9 | rcupdate.o extable.o params.o posix-timers.o \ | 9 | rcupdate.o extable.o params.o posix-timers.o \ |
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o | 12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o |
13 | 13 | ||
14 | CFLAGS_REMOVE_sched.o = -mno-spe | 14 | CFLAGS_REMOVE_sched.o = -mno-spe |
15 | 15 | ||
diff --git a/kernel/cred.c b/kernel/cred.c new file mode 100644 index 000000000000..833244a7cb05 --- /dev/null +++ b/kernel/cred.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* Task credentials management | ||
2 | * | ||
3 | * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/cred.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/key.h> | ||
15 | #include <linux/keyctl.h> | ||
16 | #include <linux/init_task.h> | ||
17 | #include <linux/security.h> | ||
18 | |||
19 | /* | ||
20 | * The initial credentials for the initial task | ||
21 | */ | ||
22 | struct cred init_cred = { | ||
23 | .usage = ATOMIC_INIT(3), | ||
24 | .securebits = SECUREBITS_DEFAULT, | ||
25 | .cap_inheritable = CAP_INIT_INH_SET, | ||
26 | .cap_permitted = CAP_FULL_SET, | ||
27 | .cap_effective = CAP_INIT_EFF_SET, | ||
28 | .cap_bset = CAP_INIT_BSET, | ||
29 | .user = INIT_USER, | ||
30 | .group_info = &init_groups, | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * The RCU callback to actually dispose of a set of credentials | ||
35 | */ | ||
36 | static void put_cred_rcu(struct rcu_head *rcu) | ||
37 | { | ||
38 | struct cred *cred = container_of(rcu, struct cred, rcu); | ||
39 | |||
40 | BUG_ON(atomic_read(&cred->usage) != 0); | ||
41 | |||
42 | key_put(cred->thread_keyring); | ||
43 | key_put(cred->request_key_auth); | ||
44 | put_group_info(cred->group_info); | ||
45 | free_uid(cred->user); | ||
46 | security_cred_free(cred); | ||
47 | kfree(cred); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * __put_cred - Destroy a set of credentials | ||
52 | * @sec: The record to release | ||
53 | * | ||
54 | * Destroy a set of credentials on which no references remain. | ||
55 | */ | ||
56 | void __put_cred(struct cred *cred) | ||
57 | { | ||
58 | call_rcu(&cred->rcu, put_cred_rcu); | ||
59 | } | ||
60 | EXPORT_SYMBOL(__put_cred); | ||
61 | |||
62 | /* | ||
63 | * Copy credentials for the new process created by fork() | ||
64 | */ | ||
65 | int copy_creds(struct task_struct *p, unsigned long clone_flags) | ||
66 | { | ||
67 | struct cred *pcred; | ||
68 | int ret; | ||
69 | |||
70 | pcred = kmemdup(p->cred, sizeof(*p->cred), GFP_KERNEL); | ||
71 | if (!pcred) | ||
72 | return -ENOMEM; | ||
73 | |||
74 | #ifdef CONFIG_SECURITY | ||
75 | pcred->security = NULL; | ||
76 | #endif | ||
77 | |||
78 | ret = security_cred_alloc(pcred); | ||
79 | if (ret < 0) { | ||
80 | kfree(pcred); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | atomic_set(&pcred->usage, 1); | ||
85 | get_group_info(pcred->group_info); | ||
86 | get_uid(pcred->user); | ||
87 | key_get(pcred->thread_keyring); | ||
88 | key_get(pcred->request_key_auth); | ||
89 | |||
90 | atomic_inc(&pcred->user->processes); | ||
91 | |||
92 | /* RCU assignment is unneeded here as no-one can have accessed this | ||
93 | * pointer yet, barring us */ | ||
94 | p->cred = pcred; | ||
95 | return 0; | ||
96 | } | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 81fdc7733908..c932e283ddfc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -146,9 +146,7 @@ void __put_task_struct(struct task_struct *tsk) | |||
146 | WARN_ON(atomic_read(&tsk->usage)); | 146 | WARN_ON(atomic_read(&tsk->usage)); |
147 | WARN_ON(tsk == current); | 147 | WARN_ON(tsk == current); |
148 | 148 | ||
149 | security_task_free(tsk); | 149 | put_cred(tsk->cred); |
150 | free_uid(tsk->__temp_cred.user); | ||
151 | put_group_info(tsk->__temp_cred.group_info); | ||
152 | delayacct_tsk_free(tsk); | 150 | delayacct_tsk_free(tsk); |
153 | 151 | ||
154 | if (!profile_handoff_task(tsk)) | 152 | if (!profile_handoff_task(tsk)) |
@@ -969,7 +967,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
969 | DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); | 967 | DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); |
970 | DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); | 968 | DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); |
971 | #endif | 969 | #endif |
972 | p->cred = &p->__temp_cred; | ||
973 | retval = -EAGAIN; | 970 | retval = -EAGAIN; |
974 | if (atomic_read(&p->cred->user->processes) >= | 971 | if (atomic_read(&p->cred->user->processes) >= |
975 | p->signal->rlim[RLIMIT_NPROC].rlim_cur) { | 972 | p->signal->rlim[RLIMIT_NPROC].rlim_cur) { |
@@ -978,9 +975,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
978 | goto bad_fork_free; | 975 | goto bad_fork_free; |
979 | } | 976 | } |
980 | 977 | ||
981 | atomic_inc(&p->cred->user->__count); | 978 | retval = copy_creds(p, clone_flags); |
982 | atomic_inc(&p->cred->user->processes); | 979 | if (retval < 0) |
983 | get_group_info(p->cred->group_info); | 980 | goto bad_fork_free; |
984 | 981 | ||
985 | /* | 982 | /* |
986 | * If multiple threads are within copy_process(), then this check | 983 | * If multiple threads are within copy_process(), then this check |
@@ -1035,9 +1032,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1035 | do_posix_clock_monotonic_gettime(&p->start_time); | 1032 | do_posix_clock_monotonic_gettime(&p->start_time); |
1036 | p->real_start_time = p->start_time; | 1033 | p->real_start_time = p->start_time; |
1037 | monotonic_to_bootbased(&p->real_start_time); | 1034 | monotonic_to_bootbased(&p->real_start_time); |
1038 | #ifdef CONFIG_SECURITY | ||
1039 | p->cred->security = NULL; | ||
1040 | #endif | ||
1041 | p->io_context = NULL; | 1035 | p->io_context = NULL; |
1042 | p->audit_context = NULL; | 1036 | p->audit_context = NULL; |
1043 | cgroup_fork(p); | 1037 | cgroup_fork(p); |
@@ -1082,10 +1076,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1082 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1076 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
1083 | sched_fork(p, clone_flags); | 1077 | sched_fork(p, clone_flags); |
1084 | 1078 | ||
1085 | if ((retval = security_task_alloc(p))) | ||
1086 | goto bad_fork_cleanup_policy; | ||
1087 | if ((retval = audit_alloc(p))) | 1079 | if ((retval = audit_alloc(p))) |
1088 | goto bad_fork_cleanup_security; | 1080 | goto bad_fork_cleanup_policy; |
1089 | /* copy all the process information */ | 1081 | /* copy all the process information */ |
1090 | if ((retval = copy_semundo(clone_flags, p))) | 1082 | if ((retval = copy_semundo(clone_flags, p))) |
1091 | goto bad_fork_cleanup_audit; | 1083 | goto bad_fork_cleanup_audit; |
@@ -1284,8 +1276,6 @@ bad_fork_cleanup_semundo: | |||
1284 | exit_sem(p); | 1276 | exit_sem(p); |
1285 | bad_fork_cleanup_audit: | 1277 | bad_fork_cleanup_audit: |
1286 | audit_free(p); | 1278 | audit_free(p); |
1287 | bad_fork_cleanup_security: | ||
1288 | security_task_free(p); | ||
1289 | bad_fork_cleanup_policy: | 1279 | bad_fork_cleanup_policy: |
1290 | #ifdef CONFIG_NUMA | 1280 | #ifdef CONFIG_NUMA |
1291 | mpol_put(p->mempolicy); | 1281 | mpol_put(p->mempolicy); |
@@ -1298,9 +1288,7 @@ bad_fork_cleanup_cgroup: | |||
1298 | bad_fork_cleanup_put_domain: | 1288 | bad_fork_cleanup_put_domain: |
1299 | module_put(task_thread_info(p)->exec_domain->module); | 1289 | module_put(task_thread_info(p)->exec_domain->module); |
1300 | bad_fork_cleanup_count: | 1290 | bad_fork_cleanup_count: |
1301 | put_group_info(p->cred->group_info); | 1291 | put_cred(p->cred); |
1302 | atomic_dec(&p->cred->user->processes); | ||
1303 | free_uid(p->cred->user); | ||
1304 | bad_fork_free: | 1292 | bad_fork_free: |
1305 | free_task(p); | 1293 | free_task(p); |
1306 | fork_out: | 1294 | fork_out: |
diff --git a/security/capability.c b/security/capability.c index 245874819036..6c4b5137ca7b 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -340,12 +340,12 @@ static int cap_task_create(unsigned long clone_flags) | |||
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
343 | static int cap_task_alloc_security(struct task_struct *p) | 343 | static int cap_cred_alloc_security(struct cred *cred) |
344 | { | 344 | { |
345 | return 0; | 345 | return 0; |
346 | } | 346 | } |
347 | 347 | ||
348 | static void cap_task_free_security(struct task_struct *p) | 348 | static void cap_cred_free(struct cred *cred) |
349 | { | 349 | { |
350 | } | 350 | } |
351 | 351 | ||
@@ -890,8 +890,8 @@ void security_fixup_ops(struct security_operations *ops) | |||
890 | set_to_cap_if_null(ops, file_receive); | 890 | set_to_cap_if_null(ops, file_receive); |
891 | set_to_cap_if_null(ops, dentry_open); | 891 | set_to_cap_if_null(ops, dentry_open); |
892 | set_to_cap_if_null(ops, task_create); | 892 | set_to_cap_if_null(ops, task_create); |
893 | set_to_cap_if_null(ops, task_alloc_security); | 893 | set_to_cap_if_null(ops, cred_alloc_security); |
894 | set_to_cap_if_null(ops, task_free_security); | 894 | set_to_cap_if_null(ops, cred_free); |
895 | set_to_cap_if_null(ops, task_setuid); | 895 | set_to_cap_if_null(ops, task_setuid); |
896 | set_to_cap_if_null(ops, task_post_setuid); | 896 | set_to_cap_if_null(ops, task_post_setuid); |
897 | set_to_cap_if_null(ops, task_setgid); | 897 | set_to_cap_if_null(ops, task_setgid); |
diff --git a/security/security.c b/security/security.c index 81c956a12300..d058f7d5b10a 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -616,14 +616,14 @@ int security_task_create(unsigned long clone_flags) | |||
616 | return security_ops->task_create(clone_flags); | 616 | return security_ops->task_create(clone_flags); |
617 | } | 617 | } |
618 | 618 | ||
619 | int security_task_alloc(struct task_struct *p) | 619 | int security_cred_alloc(struct cred *cred) |
620 | { | 620 | { |
621 | return security_ops->task_alloc_security(p); | 621 | return security_ops->cred_alloc_security(cred); |
622 | } | 622 | } |
623 | 623 | ||
624 | void security_task_free(struct task_struct *p) | 624 | void security_cred_free(struct cred *cred) |
625 | { | 625 | { |
626 | security_ops->task_free_security(p); | 626 | security_ops->cred_free(cred); |
627 | } | 627 | } |
628 | 628 | ||
629 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 629 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 328308f2882a..658435dce37c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -158,7 +158,7 @@ static int selinux_secmark_enabled(void) | |||
158 | 158 | ||
159 | /* Allocate and free functions for each kind of security blob. */ | 159 | /* Allocate and free functions for each kind of security blob. */ |
160 | 160 | ||
161 | static int task_alloc_security(struct task_struct *task) | 161 | static int cred_alloc_security(struct cred *cred) |
162 | { | 162 | { |
163 | struct task_security_struct *tsec; | 163 | struct task_security_struct *tsec; |
164 | 164 | ||
@@ -167,18 +167,11 @@ static int task_alloc_security(struct task_struct *task) | |||
167 | return -ENOMEM; | 167 | return -ENOMEM; |
168 | 168 | ||
169 | tsec->osid = tsec->sid = SECINITSID_UNLABELED; | 169 | tsec->osid = tsec->sid = SECINITSID_UNLABELED; |
170 | task->cred->security = tsec; | 170 | cred->security = tsec; |
171 | 171 | ||
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | static void task_free_security(struct task_struct *task) | ||
176 | { | ||
177 | struct task_security_struct *tsec = task->cred->security; | ||
178 | task->cred->security = NULL; | ||
179 | kfree(tsec); | ||
180 | } | ||
181 | |||
182 | static int inode_alloc_security(struct inode *inode) | 175 | static int inode_alloc_security(struct inode *inode) |
183 | { | 176 | { |
184 | struct task_security_struct *tsec = current->cred->security; | 177 | struct task_security_struct *tsec = current->cred->security; |
@@ -3184,17 +3177,17 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3184 | return task_has_perm(current, current, PROCESS__FORK); | 3177 | return task_has_perm(current, current, PROCESS__FORK); |
3185 | } | 3178 | } |
3186 | 3179 | ||
3187 | static int selinux_task_alloc_security(struct task_struct *tsk) | 3180 | static int selinux_cred_alloc_security(struct cred *cred) |
3188 | { | 3181 | { |
3189 | struct task_security_struct *tsec1, *tsec2; | 3182 | struct task_security_struct *tsec1, *tsec2; |
3190 | int rc; | 3183 | int rc; |
3191 | 3184 | ||
3192 | tsec1 = current->cred->security; | 3185 | tsec1 = current->cred->security; |
3193 | 3186 | ||
3194 | rc = task_alloc_security(tsk); | 3187 | rc = cred_alloc_security(cred); |
3195 | if (rc) | 3188 | if (rc) |
3196 | return rc; | 3189 | return rc; |
3197 | tsec2 = tsk->cred->security; | 3190 | tsec2 = cred->security; |
3198 | 3191 | ||
3199 | tsec2->osid = tsec1->osid; | 3192 | tsec2->osid = tsec1->osid; |
3200 | tsec2->sid = tsec1->sid; | 3193 | tsec2->sid = tsec1->sid; |
@@ -3208,9 +3201,14 @@ static int selinux_task_alloc_security(struct task_struct *tsk) | |||
3208 | return 0; | 3201 | return 0; |
3209 | } | 3202 | } |
3210 | 3203 | ||
3211 | static void selinux_task_free_security(struct task_struct *tsk) | 3204 | /* |
3205 | * detach and free the LSM part of a set of credentials | ||
3206 | */ | ||
3207 | static void selinux_cred_free(struct cred *cred) | ||
3212 | { | 3208 | { |
3213 | task_free_security(tsk); | 3209 | struct task_security_struct *tsec = cred->security; |
3210 | cred->security = NULL; | ||
3211 | kfree(tsec); | ||
3214 | } | 3212 | } |
3215 | 3213 | ||
3216 | static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 3214 | static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
@@ -5552,8 +5550,8 @@ static struct security_operations selinux_ops = { | |||
5552 | .dentry_open = selinux_dentry_open, | 5550 | .dentry_open = selinux_dentry_open, |
5553 | 5551 | ||
5554 | .task_create = selinux_task_create, | 5552 | .task_create = selinux_task_create, |
5555 | .task_alloc_security = selinux_task_alloc_security, | 5553 | .cred_alloc_security = selinux_cred_alloc_security, |
5556 | .task_free_security = selinux_task_free_security, | 5554 | .cred_free = selinux_cred_free, |
5557 | .task_setuid = selinux_task_setuid, | 5555 | .task_setuid = selinux_task_setuid, |
5558 | .task_post_setuid = selinux_task_post_setuid, | 5556 | .task_post_setuid = selinux_task_post_setuid, |
5559 | .task_setgid = selinux_task_setgid, | 5557 | .task_setgid = selinux_task_setgid, |
@@ -5683,7 +5681,7 @@ static __init int selinux_init(void) | |||
5683 | printk(KERN_INFO "SELinux: Initializing.\n"); | 5681 | printk(KERN_INFO "SELinux: Initializing.\n"); |
5684 | 5682 | ||
5685 | /* Set the security state for the initial task. */ | 5683 | /* Set the security state for the initial task. */ |
5686 | if (task_alloc_security(current)) | 5684 | if (cred_alloc_security(current->cred)) |
5687 | panic("SELinux: Failed to initialize initial task.\n"); | 5685 | panic("SELinux: Failed to initialize initial task.\n"); |
5688 | tsec = current->cred->security; | 5686 | tsec = current->cred->security; |
5689 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | 5687 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 791da238d049..cc837314fb0e 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -975,8 +975,8 @@ static int smack_file_receive(struct file *file) | |||
975 | */ | 975 | */ |
976 | 976 | ||
977 | /** | 977 | /** |
978 | * smack_task_alloc_security - "allocate" a task blob | 978 | * smack_cred_alloc_security - "allocate" a task cred blob |
979 | * @tsk: the task in need of a blob | 979 | * @cred: the task creds in need of a blob |
980 | * | 980 | * |
981 | * Smack isn't using copies of blobs. Everyone | 981 | * Smack isn't using copies of blobs. Everyone |
982 | * points to an immutable list. No alloc required. | 982 | * points to an immutable list. No alloc required. |
@@ -984,24 +984,24 @@ static int smack_file_receive(struct file *file) | |||
984 | * | 984 | * |
985 | * Always returns 0 | 985 | * Always returns 0 |
986 | */ | 986 | */ |
987 | static int smack_task_alloc_security(struct task_struct *tsk) | 987 | static int smack_cred_alloc_security(struct cred *cred) |
988 | { | 988 | { |
989 | tsk->cred->security = current->cred->security; | 989 | cred->security = current->cred->security; |
990 | 990 | ||
991 | return 0; | 991 | return 0; |
992 | } | 992 | } |
993 | 993 | ||
994 | /** | 994 | /** |
995 | * smack_task_free_security - "free" a task blob | 995 | * smack_cred_free - "free" task-level security credentials |
996 | * @task: the task with the blob | 996 | * @cred: the credentials in question |
997 | * | 997 | * |
998 | * Smack isn't using copies of blobs. Everyone | 998 | * Smack isn't using copies of blobs. Everyone |
999 | * points to an immutable list. The blobs never go away. | 999 | * points to an immutable list. The blobs never go away. |
1000 | * There is no leak here. | 1000 | * There is no leak here. |
1001 | */ | 1001 | */ |
1002 | static void smack_task_free_security(struct task_struct *task) | 1002 | static void smack_cred_free(struct cred *cred) |
1003 | { | 1003 | { |
1004 | task->cred->security = NULL; | 1004 | cred->security = NULL; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | /** | 1007 | /** |
@@ -2630,8 +2630,8 @@ struct security_operations smack_ops = { | |||
2630 | .file_send_sigiotask = smack_file_send_sigiotask, | 2630 | .file_send_sigiotask = smack_file_send_sigiotask, |
2631 | .file_receive = smack_file_receive, | 2631 | .file_receive = smack_file_receive, |
2632 | 2632 | ||
2633 | .task_alloc_security = smack_task_alloc_security, | 2633 | .cred_alloc_security = smack_cred_alloc_security, |
2634 | .task_free_security = smack_task_free_security, | 2634 | .cred_free = smack_cred_free, |
2635 | .task_post_setuid = cap_task_post_setuid, | 2635 | .task_post_setuid = cap_task_post_setuid, |
2636 | .task_setpgid = smack_task_setpgid, | 2636 | .task_setpgid = smack_task_setpgid, |
2637 | .task_getpgid = smack_task_getpgid, | 2637 | .task_getpgid = smack_task_getpgid, |