2 * linux/kernel/capability.c
4 * Copyright (C) 1997 Andrew Main <zefram@fysh.org>
5 * Integrated into 2.1.97+, Andrew G. Morgan <morgan@transmeta.com>
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/capability.h>
12 #include <linux/sched.h>
13 #include <linux/string.h>
15 #include <asm/uaccess.h>
17 /* Note: never hold tasklist_lock while spinning for this one */
18 spinlock_t task_capability_lock
;
21 * For sys_getproccap() and sys_setproccap(), any of the three
22 * capability set pointers may be NULL -- indicating that that set is
23 * uninteresting and/or not to be changed.
26 asmlinkage
int sys_capget(cap_user_header_t header
, cap_user_data_t dataptr
)
30 struct task_struct
*target
;
31 struct __user_cap_data_struct data
;
33 if (get_user(version
, &header
->version
))
37 if (version
!= _LINUX_CAPABILITY_VERSION
) {
38 version
= _LINUX_CAPABILITY_VERSION
;
39 if (put_user(version
, &header
->version
))
44 if (get_user(pid
, &header
->pid
))
52 spin_lock(&task_capability_lock
);
54 if (pid
&& pid
!= current
->pid
) {
55 read_lock(&tasklist_lock
);
56 target
= find_task_by_pid(pid
); /* identify target of query */
64 data
.permitted
= target
->cap_permitted
.cap
;
65 data
.inheritable
= target
->cap_inheritable
.cap
;
66 data
.effective
= target
->cap_effective
.cap
;
69 if (target
!= current
)
70 read_unlock(&tasklist_lock
);
71 spin_unlock(&task_capability_lock
);
74 if (copy_to_user(dataptr
, &data
, sizeof data
))
81 /* set capabilities for all processes in a given process group */
83 static void cap_set_pg(int pgrp
,
84 kernel_cap_t
*effective
,
85 kernel_cap_t
*inheritable
,
86 kernel_cap_t
*permitted
)
88 struct task_struct
*target
;
90 /* FIXME: do we need to have a write lock here..? */
91 read_lock(&tasklist_lock
);
92 for_each_task(target
) {
93 if (target
->pgrp
!= pgrp
)
95 target
->cap_effective
= *effective
;
96 target
->cap_inheritable
= *inheritable
;
97 target
->cap_permitted
= *permitted
;
99 read_unlock(&tasklist_lock
);
102 /* set capabilities for all processes other than 1 and self */
104 static void cap_set_all(kernel_cap_t
*effective
,
105 kernel_cap_t
*inheritable
,
106 kernel_cap_t
*permitted
)
108 struct task_struct
*target
;
110 /* FIXME: do we need to have a write lock here..? */
111 read_lock(&tasklist_lock
);
112 /* ALL means everyone other than self or 'init' */
113 for_each_task(target
) {
114 if (target
== current
|| target
->pid
== 1)
116 target
->cap_effective
= *effective
;
117 target
->cap_inheritable
= *inheritable
;
118 target
->cap_permitted
= *permitted
;
120 read_unlock(&tasklist_lock
);
124 * The restrictions on setting capabilities are specified as:
126 * [pid is for the 'target' task. 'current' is the calling task.]
128 * I: any raised capabilities must be a subset of the (old current) Permitted
129 * P: any raised capabilities must be a subset of the (old current) permitted
130 * E: must be set to a subset of (new target) Permitted
133 asmlinkage
int sys_capset(cap_user_header_t header
, const cap_user_data_t data
)
135 kernel_cap_t inheritable
, permitted
, effective
;
137 struct task_struct
*target
;
140 if (get_user(version
, &header
->version
))
143 if (version
!= _LINUX_CAPABILITY_VERSION
) {
144 version
= _LINUX_CAPABILITY_VERSION
;
145 if (put_user(version
, &header
->version
))
150 if (get_user(pid
, &header
->pid
))
153 if (pid
&& !capable(CAP_SETPCAP
))
156 if (copy_from_user(&effective
, &data
->effective
, sizeof(effective
)) ||
157 copy_from_user(&inheritable
, &data
->inheritable
, sizeof(inheritable
)) ||
158 copy_from_user(&permitted
, &data
->permitted
, sizeof(permitted
)))
162 spin_lock(&task_capability_lock
);
164 if (pid
> 0 && pid
!= current
->pid
) {
165 read_lock(&tasklist_lock
);
166 target
= find_task_by_pid(pid
); /* identify target of query */
176 /* verify restrictions on target's new Inheritable set */
177 if (!cap_issubset(inheritable
,
178 cap_combine(target
->cap_inheritable
,
179 current
->cap_permitted
))) {
183 /* verify restrictions on target's new Permitted set */
184 if (!cap_issubset(permitted
,
185 cap_combine(target
->cap_permitted
,
186 current
->cap_permitted
))) {
190 /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
191 if (!cap_issubset(effective
, permitted
)) {
195 /* having verified that the proposed changes are legal,
196 we now put them into effect. */
200 if (pid
== -1) /* all procs other than current and init */
201 cap_set_all(&effective
, &inheritable
, &permitted
);
203 else /* all procs in process group */
204 cap_set_pg(-pid
, &effective
, &inheritable
, &permitted
);
207 /* FIXME: do we need to have a write lock here..? */
208 target
->cap_effective
= effective
;
209 target
->cap_inheritable
= inheritable
;
210 target
->cap_permitted
= permitted
;
214 if (target
!= current
) {
215 read_unlock(&tasklist_lock
);
218 spin_unlock(&task_capability_lock
);