diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:16 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:16 -0500 |
commit | b6dff3ec5e116e3af6f537d4caedcad6b9e5082a (patch) | |
tree | 9e76f972eb7ce9b84e0146c8e4126a3f86acb428 /include/linux | |
parent | 15a2460ed0af7538ca8e6c610fe607a2cd9da142 (diff) |
CRED: Separate task security context from task_struct
Separate the task security context from task_struct. At this point, the
security data is temporarily embedded in the task_struct with two pointers
pointing to it.
Note that the Alpha arch is altered as it refers to (E)UID and (E)GID in
entry.S via asm-offsets.
With comment fixes Signed-off-by: Marc Dionne <marc.c.dionne@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/cred.h | 155 | ||||
-rw-r--r-- | include/linux/init_task.h | 24 | ||||
-rw-r--r-- | include/linux/sched.h | 52 | ||||
-rw-r--r-- | include/linux/securebits.h | 2 |
4 files changed, 155 insertions, 78 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h index b69222cc1fd2..3e65587a72e5 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
@@ -12,39 +12,150 @@ | |||
12 | #ifndef _LINUX_CRED_H | 12 | #ifndef _LINUX_CRED_H |
13 | #define _LINUX_CRED_H | 13 | #define _LINUX_CRED_H |
14 | 14 | ||
15 | #define get_current_user() (get_uid(current->user)) | 15 | #include <linux/capability.h> |
16 | 16 | #include <linux/key.h> | |
17 | #define task_uid(task) ((task)->uid) | 17 | #include <asm/atomic.h> |
18 | #define task_gid(task) ((task)->gid) | 18 | |
19 | #define task_euid(task) ((task)->euid) | 19 | struct user_struct; |
20 | #define task_egid(task) ((task)->egid) | 20 | struct cred; |
21 | 21 | ||
22 | #define current_uid() (current->uid) | 22 | /* |
23 | #define current_gid() (current->gid) | 23 | * COW Supplementary groups list |
24 | #define current_euid() (current->euid) | 24 | */ |
25 | #define current_egid() (current->egid) | 25 | #define NGROUPS_SMALL 32 |
26 | #define current_suid() (current->suid) | 26 | #define NGROUPS_PER_BLOCK ((unsigned int)(PAGE_SIZE / sizeof(gid_t))) |
27 | #define current_sgid() (current->sgid) | 27 | |
28 | #define current_fsuid() (current->fsuid) | 28 | struct group_info { |
29 | #define current_fsgid() (current->fsgid) | 29 | atomic_t usage; |
30 | #define current_cap() (current->cap_effective) | 30 | int ngroups; |
31 | int nblocks; | ||
32 | gid_t small_block[NGROUPS_SMALL]; | ||
33 | gid_t *blocks[0]; | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * get_group_info - Get a reference to a group info structure | ||
38 | * @group_info: The group info to reference | ||
39 | * | ||
40 | * This must be called with the owning task locked (via task_lock()) when task | ||
41 | * != current. The reason being that the vast majority of callers are looking | ||
42 | * at current->group_info, which can not be changed except by the current task. | ||
43 | * Changing current->group_info requires the task lock, too. | ||
44 | */ | ||
45 | #define get_group_info(group_info) \ | ||
46 | do { \ | ||
47 | atomic_inc(&(group_info)->usage); \ | ||
48 | } while (0) | ||
49 | |||
50 | /** | ||
51 | * put_group_info - Release a reference to a group info structure | ||
52 | * @group_info: The group info to release | ||
53 | */ | ||
54 | #define put_group_info(group_info) \ | ||
55 | do { \ | ||
56 | if (atomic_dec_and_test(&(group_info)->usage)) \ | ||
57 | groups_free(group_info); \ | ||
58 | } while (0) | ||
59 | |||
60 | extern struct group_info *groups_alloc(int); | ||
61 | extern void groups_free(struct group_info *); | ||
62 | extern int set_current_groups(struct group_info *); | ||
63 | extern int set_groups(struct cred *, struct group_info *); | ||
64 | extern int groups_search(struct group_info *, gid_t); | ||
65 | |||
66 | /* access the groups "array" with this macro */ | ||
67 | #define GROUP_AT(gi, i) \ | ||
68 | ((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK]) | ||
69 | |||
70 | extern int in_group_p(gid_t); | ||
71 | extern int in_egroup_p(gid_t); | ||
72 | |||
73 | /* | ||
74 | * The security context of a task | ||
75 | * | ||
76 | * The parts of the context break down into two categories: | ||
77 | * | ||
78 | * (1) The objective context of a task. These parts are used when some other | ||
79 | * task is attempting to affect this one. | ||
80 | * | ||
81 | * (2) The subjective context. These details are used when the task is acting | ||
82 | * upon another object, be that a file, a task, a key or whatever. | ||
83 | * | ||
84 | * Note that some members of this structure belong to both categories - the | ||
85 | * LSM security pointer for instance. | ||
86 | * | ||
87 | * A task has two security pointers. task->real_cred points to the objective | ||
88 | * context that defines that task's actual details. The objective part of this | ||
89 | * context is used whenever that task is acted upon. | ||
90 | * | ||
91 | * task->cred points to the subjective context that defines the details of how | ||
92 | * that task is going to act upon another object. This may be overridden | ||
93 | * temporarily to point to another security context, but normally points to the | ||
94 | * same context as task->real_cred. | ||
95 | */ | ||
96 | struct cred { | ||
97 | atomic_t usage; | ||
98 | uid_t uid; /* real UID of the task */ | ||
99 | gid_t gid; /* real GID of the task */ | ||
100 | uid_t suid; /* saved UID of the task */ | ||
101 | gid_t sgid; /* saved GID of the task */ | ||
102 | uid_t euid; /* effective UID of the task */ | ||
103 | gid_t egid; /* effective GID of the task */ | ||
104 | uid_t fsuid; /* UID for VFS ops */ | ||
105 | gid_t fsgid; /* GID for VFS ops */ | ||
106 | unsigned securebits; /* SUID-less security management */ | ||
107 | kernel_cap_t cap_inheritable; /* caps our children can inherit */ | ||
108 | kernel_cap_t cap_permitted; /* caps we're permitted */ | ||
109 | kernel_cap_t cap_effective; /* caps we can actually use */ | ||
110 | kernel_cap_t cap_bset; /* capability bounding set */ | ||
111 | #ifdef CONFIG_KEYS | ||
112 | unsigned char jit_keyring; /* default keyring to attach requested | ||
113 | * keys to */ | ||
114 | struct key *thread_keyring; /* keyring private to this thread */ | ||
115 | struct key *request_key_auth; /* assumed request_key authority */ | ||
116 | #endif | ||
117 | #ifdef CONFIG_SECURITY | ||
118 | void *security; /* subjective LSM security */ | ||
119 | #endif | ||
120 | struct user_struct *user; /* real user ID subscription */ | ||
121 | struct group_info *group_info; /* supplementary groups for euid/fsgid */ | ||
122 | struct rcu_head rcu; /* RCU deletion hook */ | ||
123 | spinlock_t lock; /* lock for pointer changes */ | ||
124 | }; | ||
125 | |||
126 | #define get_current_user() (get_uid(current->cred->user)) | ||
127 | |||
128 | #define task_uid(task) ((task)->cred->uid) | ||
129 | #define task_gid(task) ((task)->cred->gid) | ||
130 | #define task_euid(task) ((task)->cred->euid) | ||
131 | #define task_egid(task) ((task)->cred->egid) | ||
132 | |||
133 | #define current_uid() (current->cred->uid) | ||
134 | #define current_gid() (current->cred->gid) | ||
135 | #define current_euid() (current->cred->euid) | ||
136 | #define current_egid() (current->cred->egid) | ||
137 | #define current_suid() (current->cred->suid) | ||
138 | #define current_sgid() (current->cred->sgid) | ||
139 | #define current_fsuid() (current->cred->fsuid) | ||
140 | #define current_fsgid() (current->cred->fsgid) | ||
141 | #define current_cap() (current->cred->cap_effective) | ||
31 | 142 | ||
32 | #define current_uid_gid(_uid, _gid) \ | 143 | #define current_uid_gid(_uid, _gid) \ |
33 | do { \ | 144 | do { \ |
34 | *(_uid) = current->uid; \ | 145 | *(_uid) = current->cred->uid; \ |
35 | *(_gid) = current->gid; \ | 146 | *(_gid) = current->cred->gid; \ |
36 | } while(0) | 147 | } while(0) |
37 | 148 | ||
38 | #define current_euid_egid(_uid, _gid) \ | 149 | #define current_euid_egid(_uid, _gid) \ |
39 | do { \ | 150 | do { \ |
40 | *(_uid) = current->euid; \ | 151 | *(_uid) = current->cred->euid; \ |
41 | *(_gid) = current->egid; \ | 152 | *(_gid) = current->cred->egid; \ |
42 | } while(0) | 153 | } while(0) |
43 | 154 | ||
44 | #define current_fsuid_fsgid(_uid, _gid) \ | 155 | #define current_fsuid_fsgid(_uid, _gid) \ |
45 | do { \ | 156 | do { \ |
46 | *(_uid) = current->fsuid; \ | 157 | *(_uid) = current->cred->fsuid; \ |
47 | *(_gid) = current->fsgid; \ | 158 | *(_gid) = current->cred->fsgid; \ |
48 | } while(0) | 159 | } while(0) |
49 | 160 | ||
50 | #endif /* _LINUX_CRED_H */ | 161 | #endif /* _LINUX_CRED_H */ |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 23fd8909b9e5..9de41ccd67b5 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -113,6 +113,21 @@ extern struct group_info init_groups; | |||
113 | # define CAP_INIT_BSET CAP_INIT_EFF_SET | 113 | # define CAP_INIT_BSET CAP_INIT_EFF_SET |
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | extern struct cred init_cred; | ||
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 | |||
116 | /* | 131 | /* |
117 | * INIT_TASK is used to set up the first task table, touch at | 132 | * INIT_TASK is used to set up the first task table, touch at |
118 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 133 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
@@ -147,13 +162,8 @@ extern struct group_info init_groups; | |||
147 | .children = LIST_HEAD_INIT(tsk.children), \ | 162 | .children = LIST_HEAD_INIT(tsk.children), \ |
148 | .sibling = LIST_HEAD_INIT(tsk.sibling), \ | 163 | .sibling = LIST_HEAD_INIT(tsk.sibling), \ |
149 | .group_leader = &tsk, \ | 164 | .group_leader = &tsk, \ |
150 | .group_info = &init_groups, \ | 165 | .__temp_cred = INIT_CRED(tsk.__temp_cred), \ |
151 | .cap_effective = CAP_INIT_EFF_SET, \ | 166 | .cred = &tsk.__temp_cred, \ |
152 | .cap_inheritable = CAP_INIT_INH_SET, \ | ||
153 | .cap_permitted = CAP_FULL_SET, \ | ||
154 | .cap_bset = CAP_INIT_BSET, \ | ||
155 | .securebits = SECUREBITS_DEFAULT, \ | ||
156 | .user = INIT_USER, \ | ||
157 | .comm = "swapper", \ | 167 | .comm = "swapper", \ |
158 | .thread = INIT_THREAD, \ | 168 | .thread = INIT_THREAD, \ |
159 | .fs = &init_fs, \ | 169 | .fs = &init_fs, \ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index b483f39a7112..c8b92502354d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -660,6 +660,7 @@ extern struct user_struct *find_user(uid_t); | |||
660 | extern struct user_struct root_user; | 660 | extern struct user_struct root_user; |
661 | #define INIT_USER (&root_user) | 661 | #define INIT_USER (&root_user) |
662 | 662 | ||
663 | |||
663 | struct backing_dev_info; | 664 | struct backing_dev_info; |
664 | struct reclaim_state; | 665 | struct reclaim_state; |
665 | 666 | ||
@@ -883,38 +884,7 @@ partition_sched_domains(int ndoms_new, cpumask_t *doms_new, | |||
883 | #endif /* !CONFIG_SMP */ | 884 | #endif /* !CONFIG_SMP */ |
884 | 885 | ||
885 | struct io_context; /* See blkdev.h */ | 886 | struct io_context; /* See blkdev.h */ |
886 | #define NGROUPS_SMALL 32 | ||
887 | #define NGROUPS_PER_BLOCK ((unsigned int)(PAGE_SIZE / sizeof(gid_t))) | ||
888 | struct group_info { | ||
889 | int ngroups; | ||
890 | atomic_t usage; | ||
891 | gid_t small_block[NGROUPS_SMALL]; | ||
892 | int nblocks; | ||
893 | gid_t *blocks[0]; | ||
894 | }; | ||
895 | |||
896 | /* | ||
897 | * get_group_info() must be called with the owning task locked (via task_lock()) | ||
898 | * when task != current. The reason being that the vast majority of callers are | ||
899 | * looking at current->group_info, which can not be changed except by the | ||
900 | * current task. Changing current->group_info requires the task lock, too. | ||
901 | */ | ||
902 | #define get_group_info(group_info) do { \ | ||
903 | atomic_inc(&(group_info)->usage); \ | ||
904 | } while (0) | ||
905 | 887 | ||
906 | #define put_group_info(group_info) do { \ | ||
907 | if (atomic_dec_and_test(&(group_info)->usage)) \ | ||
908 | groups_free(group_info); \ | ||
909 | } while (0) | ||
910 | |||
911 | extern struct group_info *groups_alloc(int gidsetsize); | ||
912 | extern void groups_free(struct group_info *group_info); | ||
913 | extern int set_current_groups(struct group_info *group_info); | ||
914 | extern int groups_search(struct group_info *group_info, gid_t grp); | ||
915 | /* access the groups "array" with this macro */ | ||
916 | #define GROUP_AT(gi, i) \ | ||
917 | ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK]) | ||
918 | 888 | ||
919 | #ifdef ARCH_HAS_PREFETCH_SWITCH_STACK | 889 | #ifdef ARCH_HAS_PREFETCH_SWITCH_STACK |
920 | extern void prefetch_stack(struct task_struct *t); | 890 | extern void prefetch_stack(struct task_struct *t); |
@@ -1181,17 +1151,9 @@ struct task_struct { | |||
1181 | struct list_head cpu_timers[3]; | 1151 | struct list_head cpu_timers[3]; |
1182 | 1152 | ||
1183 | /* process credentials */ | 1153 | /* process credentials */ |
1184 | uid_t uid,euid,suid,fsuid; | 1154 | struct cred __temp_cred __deprecated; /* temporary credentials to be removed */ |
1185 | gid_t gid,egid,sgid,fsgid; | 1155 | struct cred *cred; /* actual/objective task credentials */ |
1186 | struct group_info *group_info; | 1156 | |
1187 | kernel_cap_t cap_effective, cap_inheritable, cap_permitted, cap_bset; | ||
1188 | struct user_struct *user; | ||
1189 | unsigned securebits; | ||
1190 | #ifdef CONFIG_KEYS | ||
1191 | unsigned char jit_keyring; /* default keyring to attach requested keys to */ | ||
1192 | struct key *request_key_auth; /* assumed request_key authority */ | ||
1193 | struct key *thread_keyring; /* keyring private to this thread */ | ||
1194 | #endif | ||
1195 | char comm[TASK_COMM_LEN]; /* executable name excluding path | 1157 | char comm[TASK_COMM_LEN]; /* executable name excluding path |
1196 | - access with [gs]et_task_comm (which lock | 1158 | - access with [gs]et_task_comm (which lock |
1197 | it with task_lock()) | 1159 | it with task_lock()) |
@@ -1228,9 +1190,6 @@ struct task_struct { | |||
1228 | int (*notifier)(void *priv); | 1190 | int (*notifier)(void *priv); |
1229 | void *notifier_data; | 1191 | void *notifier_data; |
1230 | sigset_t *notifier_mask; | 1192 | sigset_t *notifier_mask; |
1231 | #ifdef CONFIG_SECURITY | ||
1232 | void *security; | ||
1233 | #endif | ||
1234 | struct audit_context *audit_context; | 1193 | struct audit_context *audit_context; |
1235 | #ifdef CONFIG_AUDITSYSCALL | 1194 | #ifdef CONFIG_AUDITSYSCALL |
1236 | uid_t loginuid; | 1195 | uid_t loginuid; |
@@ -1787,9 +1746,6 @@ extern void wake_up_new_task(struct task_struct *tsk, | |||
1787 | extern void sched_fork(struct task_struct *p, int clone_flags); | 1746 | extern void sched_fork(struct task_struct *p, int clone_flags); |
1788 | extern void sched_dead(struct task_struct *p); | 1747 | extern void sched_dead(struct task_struct *p); |
1789 | 1748 | ||
1790 | extern int in_group_p(gid_t); | ||
1791 | extern int in_egroup_p(gid_t); | ||
1792 | |||
1793 | extern void proc_caches_init(void); | 1749 | extern void proc_caches_init(void); |
1794 | extern void flush_signals(struct task_struct *); | 1750 | extern void flush_signals(struct task_struct *); |
1795 | extern void ignore_signals(struct task_struct *); | 1751 | extern void ignore_signals(struct task_struct *); |
diff --git a/include/linux/securebits.h b/include/linux/securebits.h index 92f09bdf1175..6d389491bfa2 100644 --- a/include/linux/securebits.h +++ b/include/linux/securebits.h | |||
@@ -32,7 +32,7 @@ | |||
32 | setting is locked or not. A setting which is locked cannot be | 32 | setting is locked or not. A setting which is locked cannot be |
33 | changed from user-level. */ | 33 | changed from user-level. */ |
34 | #define issecure_mask(X) (1 << (X)) | 34 | #define issecure_mask(X) (1 << (X)) |
35 | #define issecure(X) (issecure_mask(X) & current->securebits) | 35 | #define issecure(X) (issecure_mask(X) & current->cred->securebits) |
36 | 36 | ||
37 | #define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ | 37 | #define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ |
38 | issecure_mask(SECURE_NO_SETUID_FIXUP) | \ | 38 | issecure_mask(SECURE_NO_SETUID_FIXUP) | \ |