aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge E. Hallyn <serue@us.ibm.com>2008-02-05 01:29:45 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:20 -0500
commit3b7391de67da515c91f48aa371de77cb6cc5c07e (patch)
tree22b9f5d9d1c36b374eb5765219aca3c7e1f23486
parent46c383cc4530ccc438cb325e92e11eb21dd3d4fc (diff)
capabilities: introduce per-process capability bounding set
The capability bounding set is a set beyond which capabilities cannot grow. Currently cap_bset is per-system. It can be manipulated through sysctl, but only init can add capabilities. Root can remove capabilities. By default it includes all caps except CAP_SETPCAP. This patch makes the bounding set per-process when file capabilities are enabled. It is inherited at fork from parent. Noone can add elements, CAP_SETPCAP is required to remove them. One example use of this is to start a safer container. For instance, until device namespaces or per-container device whitelists are introduced, it is best to take CAP_MKNOD away from a container. The bounding set will not affect pP and pE immediately. It will only affect pP' and pE' after subsequent exec()s. It also does not affect pI, and exec() does not constrain pI'. So to really start a shell with no way of regain CAP_MKNOD, you would do prctl(PR_CAPBSET_DROP, CAP_MKNOD); cap_t cap = cap_get_proc(); cap_value_t caparray[1]; caparray[0] = CAP_MKNOD; cap_set_flag(cap, CAP_INHERITABLE, 1, caparray, CAP_DROP); cap_set_proc(cap); cap_free(cap); The following test program will get and set the bounding set (but not pI). For instance ./bset get (lists capabilities in bset) ./bset drop cap_net_raw (starts shell with new bset) (use capset, setuid binary, or binary with file capabilities to try to increase caps) ************************************************************ cap_bound.c ************************************************************ #include <sys/prctl.h> #include <linux/capability.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef PR_CAPBSET_READ #define PR_CAPBSET_READ 23 #endif #ifndef PR_CAPBSET_DROP #define PR_CAPBSET_DROP 24 #endif int usage(char *me) { printf("Usage: %s get\n", me); printf(" %s drop <capability>\n", me); return 1; } #define numcaps 32 char *captable[numcaps] = { "cap_chown", "cap_dac_override", "cap_dac_read_search", "cap_fowner", "cap_fsetid", "cap_kill", "cap_setgid", "cap_setuid", "cap_setpcap", "cap_linux_immutable", "cap_net_bind_service", "cap_net_broadcast", "cap_net_admin", "cap_net_raw", "cap_ipc_lock", "cap_ipc_owner", "cap_sys_module", "cap_sys_rawio", "cap_sys_chroot", "cap_sys_ptrace", "cap_sys_pacct", "cap_sys_admin", "cap_sys_boot", "cap_sys_nice", "cap_sys_resource", "cap_sys_time", "cap_sys_tty_config", "cap_mknod", "cap_lease", "cap_audit_write", "cap_audit_control", "cap_setfcap" }; int getbcap(void) { int comma=0; unsigned long i; int ret; printf("i know of %d capabilities\n", numcaps); printf("capability bounding set:"); for (i=0; i<numcaps; i++) { ret = prctl(PR_CAPBSET_READ, i); if (ret < 0) perror("prctl"); else if (ret==1) printf("%s%s", (comma++) ? ", " : " ", captable[i]); } printf("\n"); return 0; } int capdrop(char *str) { unsigned long i; int found=0; for (i=0; i<numcaps; i++) { if (strcmp(captable[i], str) == 0) { found=1; break; } } if (!found) return 1; if (prctl(PR_CAPBSET_DROP, i)) { perror("prctl"); return 1; } return 0; } int main(int argc, char *argv[]) { if (argc<2) return usage(argv[0]); if (strcmp(argv[1], "get")==0) return getbcap(); if (strcmp(argv[1], "drop")!=0 || argc<3) return usage(argv[0]); if (capdrop(argv[2])) { printf("unknown capability\n"); return 1; } return execl("/bin/bash", "/bin/bash", NULL); } ************************************************************ [serue@us.ibm.com: fix typo] Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Signed-off-by: Andrew G. Morgan <morgan@kernel.org> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: James Morris <jmorris@namei.org> Cc: Chris Wright <chrisw@sous-sol.org> Cc: Casey Schaufler <casey@schaufler-ca.com>a Signed-off-by: "Serge E. Hallyn" <serue@us.ibm.com> Tested-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/capability.h11
-rw-r--r--include/linux/init_task.h13
-rw-r--r--include/linux/prctl.h4
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/security.h5
-rw-r--r--include/linux/sysctl.h3
-rw-r--r--kernel/fork.c1
-rw-r--r--kernel/sys.c13
-rw-r--r--kernel/sysctl.c35
-rw-r--r--kernel/sysctl_check.c7
-rw-r--r--security/commoncap.c44
11 files changed, 67 insertions, 71 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h
index a1d93da67fe9..ffe7bab8c3a0 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -152,7 +152,9 @@ typedef struct kernel_cap_struct {
152 * Transfer any capability in your permitted set to any pid, 152 * Transfer any capability in your permitted set to any pid,
153 * remove any capability in your permitted set from any pid 153 * remove any capability in your permitted set from any pid
154 * With VFS support for capabilities (neither of above, but) 154 * With VFS support for capabilities (neither of above, but)
155 * Add any capability to the current process' inheritable set 155 * Add any capability from current's capability bounding set
156 * to the current process' inheritable set
157 * Allow taking bits out of capability bounding set
156 */ 158 */
157 159
158#define CAP_SETPCAP 8 160#define CAP_SETPCAP 8
@@ -202,7 +204,6 @@ typedef struct kernel_cap_struct {
202#define CAP_IPC_OWNER 15 204#define CAP_IPC_OWNER 15
203 205
204/* Insert and remove kernel modules - modify kernel without limit */ 206/* Insert and remove kernel modules - modify kernel without limit */
205/* Modify cap_bset */
206#define CAP_SYS_MODULE 16 207#define CAP_SYS_MODULE 16
207 208
208/* Allow ioperm/iopl access */ 209/* Allow ioperm/iopl access */
@@ -314,6 +315,10 @@ typedef struct kernel_cap_struct {
314 315
315#define CAP_SETFCAP 31 316#define CAP_SETFCAP 31
316 317
318#define CAP_LAST_CAP CAP_SETFCAP
319
320#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
321
317/* 322/*
318 * Bit location of each capability (used by user-space library and kernel) 323 * Bit location of each capability (used by user-space library and kernel)
319 */ 324 */
@@ -465,6 +470,8 @@ extern const kernel_cap_t __cap_init_eff_set;
465int capable(int cap); 470int capable(int cap);
466int __capable(struct task_struct *t, int cap); 471int __capable(struct task_struct *t, int cap);
467 472
473extern long cap_prctl_drop(unsigned long cap);
474
468#endif /* __KERNEL__ */ 475#endif /* __KERNEL__ */
469 476
470#endif /* !_LINUX_CAPABILITY_H */ 477#endif /* !_LINUX_CAPABILITY_H */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index f42663eaf655..1f74e1d7415f 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -121,6 +121,18 @@ extern struct group_info init_groups;
121#else 121#else
122#define INIT_IDS 122#define INIT_IDS
123#endif 123#endif
124
125#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
126/*
127 * Because of the reduced scope of CAP_SETPCAP when filesystem
128 * capabilities are in effect, it is safe to allow CAP_SETPCAP to
129 * be available in the default configuration.
130 */
131# define CAP_INIT_BSET CAP_FULL_SET
132#else
133# define CAP_INIT_BSET CAP_INIT_EFF_SET
134#endif
135
124/* 136/*
125 * INIT_TASK is used to set up the first task table, touch at 137 * INIT_TASK is used to set up the first task table, touch at
126 * your own risk!. Base=0, limit=0x1fffff (=2MB) 138 * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -156,6 +168,7 @@ extern struct group_info init_groups;
156 .cap_effective = CAP_INIT_EFF_SET, \ 168 .cap_effective = CAP_INIT_EFF_SET, \
157 .cap_inheritable = CAP_INIT_INH_SET, \ 169 .cap_inheritable = CAP_INIT_INH_SET, \
158 .cap_permitted = CAP_FULL_SET, \ 170 .cap_permitted = CAP_FULL_SET, \
171 .cap_bset = CAP_INIT_BSET, \
159 .keep_capabilities = 0, \ 172 .keep_capabilities = 0, \
160 .user = INIT_USER, \ 173 .user = INIT_USER, \
161 .comm = "swapper", \ 174 .comm = "swapper", \
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index e2eff9079fe9..3800639775ae 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -63,4 +63,8 @@
63#define PR_GET_SECCOMP 21 63#define PR_GET_SECCOMP 21
64#define PR_SET_SECCOMP 22 64#define PR_SET_SECCOMP 22
65 65
66/* Get/set the capability bounding set */
67#define PR_CAPBSET_READ 23
68#define PR_CAPBSET_DROP 24
69
66#endif /* _LINUX_PRCTL_H */ 70#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index c30d174a02fa..9c13be3a21e8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1098,7 +1098,7 @@ struct task_struct {
1098 uid_t uid,euid,suid,fsuid; 1098 uid_t uid,euid,suid,fsuid;
1099 gid_t gid,egid,sgid,fsgid; 1099 gid_t gid,egid,sgid,fsgid;
1100 struct group_info *group_info; 1100 struct group_info *group_info;
1101 kernel_cap_t cap_effective, cap_inheritable, cap_permitted; 1101 kernel_cap_t cap_effective, cap_inheritable, cap_permitted, cap_bset;
1102 unsigned keep_capabilities:1; 1102 unsigned keep_capabilities:1;
1103 struct user_struct *user; 1103 struct user_struct *user;
1104#ifdef CONFIG_KEYS 1104#ifdef CONFIG_KEYS
diff --git a/include/linux/security.h b/include/linux/security.h
index 9d289e726fd8..fe52cdeab0a6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -40,11 +40,6 @@
40#define ROOTCONTEXT_MNT 0x04 40#define ROOTCONTEXT_MNT 0x04
41#define DEFCONTEXT_MNT 0x08 41#define DEFCONTEXT_MNT 0x08
42 42
43/*
44 * Bounding set
45 */
46extern kernel_cap_t cap_bset;
47
48extern unsigned securebits; 43extern unsigned securebits;
49 44
50struct ctl_table; 45struct ctl_table;
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index bf4ae4e138f7..571f01d20a86 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -102,7 +102,6 @@ enum
102 KERN_NODENAME=7, 102 KERN_NODENAME=7,
103 KERN_DOMAINNAME=8, 103 KERN_DOMAINNAME=8,
104 104
105 KERN_CAP_BSET=14, /* int: capability bounding set */
106 KERN_PANIC=15, /* int: panic timeout */ 105 KERN_PANIC=15, /* int: panic timeout */
107 KERN_REALROOTDEV=16, /* real root device to mount after initrd */ 106 KERN_REALROOTDEV=16, /* real root device to mount after initrd */
108 107
@@ -965,8 +964,6 @@ extern int proc_dostring(struct ctl_table *, int, struct file *,
965 void __user *, size_t *, loff_t *); 964 void __user *, size_t *, loff_t *);
966extern int proc_dointvec(struct ctl_table *, int, struct file *, 965extern int proc_dointvec(struct ctl_table *, int, struct file *,
967 void __user *, size_t *, loff_t *); 966 void __user *, size_t *, loff_t *);
968extern int proc_dointvec_bset(struct ctl_table *, int, struct file *,
969 void __user *, size_t *, loff_t *);
970extern int proc_dointvec_minmax(struct ctl_table *, int, struct file *, 967extern int proc_dointvec_minmax(struct ctl_table *, int, struct file *,
971 void __user *, size_t *, loff_t *); 968 void __user *, size_t *, loff_t *);
972extern int proc_dointvec_jiffies(struct ctl_table *, int, struct file *, 969extern int proc_dointvec_jiffies(struct ctl_table *, int, struct file *,
diff --git a/kernel/fork.c b/kernel/fork.c
index 1160f87ba700..2b55b74cd999 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1118,6 +1118,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1118#ifdef CONFIG_SECURITY 1118#ifdef CONFIG_SECURITY
1119 p->security = NULL; 1119 p->security = NULL;
1120#endif 1120#endif
1121 p->cap_bset = current->cap_bset;
1121 p->io_context = NULL; 1122 p->io_context = NULL;
1122 p->audit_context = NULL; 1123 p->audit_context = NULL;
1123 cgroup_fork(p); 1124 cgroup_fork(p);
diff --git a/kernel/sys.c b/kernel/sys.c
index d1fe71eb4546..4162d12390b6 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1637,7 +1637,7 @@ asmlinkage long sys_umask(int mask)
1637 mask = xchg(&current->fs->umask, mask & S_IRWXUGO); 1637 mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
1638 return mask; 1638 return mask;
1639} 1639}
1640 1640
1641asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, 1641asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1642 unsigned long arg4, unsigned long arg5) 1642 unsigned long arg4, unsigned long arg5)
1643{ 1643{
@@ -1742,6 +1742,17 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1742 error = prctl_set_seccomp(arg2); 1742 error = prctl_set_seccomp(arg2);
1743 break; 1743 break;
1744 1744
1745 case PR_CAPBSET_READ:
1746 if (!cap_valid(arg2))
1747 return -EINVAL;
1748 return !!cap_raised(current->cap_bset, arg2);
1749 case PR_CAPBSET_DROP:
1750#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
1751 return cap_prctl_drop(arg2);
1752#else
1753 return -EINVAL;
1754#endif
1755
1745 default: 1756 default:
1746 error = -EINVAL; 1757 error = -EINVAL;
1747 break; 1758 break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d0b47b859067..5e2ad5bf88e2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -419,15 +419,6 @@ static struct ctl_table kern_table[] = {
419 .proc_handler = &proc_dointvec, 419 .proc_handler = &proc_dointvec,
420 }, 420 },
421#endif 421#endif
422#ifdef CONFIG_SECURITY_CAPABILITIES
423 {
424 .procname = "cap-bound",
425 .data = &cap_bset,
426 .maxlen = sizeof(kernel_cap_t),
427 .mode = 0600,
428 .proc_handler = &proc_dointvec_bset,
429 },
430#endif /* def CONFIG_SECURITY_CAPABILITIES */
431#ifdef CONFIG_BLK_DEV_INITRD 422#ifdef CONFIG_BLK_DEV_INITRD
432 { 423 {
433 .ctl_name = KERN_REALROOTDEV, 424 .ctl_name = KERN_REALROOTDEV,
@@ -2096,26 +2087,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
2096 return 0; 2087 return 0;
2097} 2088}
2098 2089
2099#ifdef CONFIG_SECURITY_CAPABILITIES
2100/*
2101 * init may raise the set.
2102 */
2103
2104int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
2105 void __user *buffer, size_t *lenp, loff_t *ppos)
2106{
2107 int op;
2108
2109 if (write && !capable(CAP_SYS_MODULE)) {
2110 return -EPERM;
2111 }
2112
2113 op = is_global_init(current) ? OP_SET : OP_AND;
2114 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2115 do_proc_dointvec_bset_conv,&op);
2116}
2117#endif /* def CONFIG_SECURITY_CAPABILITIES */
2118
2119/* 2090/*
2120 * Taint values can only be increased 2091 * Taint values can only be increased
2121 */ 2092 */
@@ -2529,12 +2500,6 @@ int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
2529 return -ENOSYS; 2500 return -ENOSYS;
2530} 2501}
2531 2502
2532int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
2533 void __user *buffer, size_t *lenp, loff_t *ppos)
2534{
2535 return -ENOSYS;
2536}
2537
2538int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp, 2503int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
2539 void __user *buffer, size_t *lenp, loff_t *ppos) 2504 void __user *buffer, size_t *lenp, loff_t *ppos)
2540{ 2505{
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index c3206fa50048..006365b69eaf 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -37,10 +37,6 @@ static struct trans_ctl_table trans_kern_table[] = {
37 { KERN_NODENAME, "hostname" }, 37 { KERN_NODENAME, "hostname" },
38 { KERN_DOMAINNAME, "domainname" }, 38 { KERN_DOMAINNAME, "domainname" },
39 39
40#ifdef CONFIG_SECURITY_CAPABILITIES
41 { KERN_CAP_BSET, "cap-bound" },
42#endif /* def CONFIG_SECURITY_CAPABILITIES */
43
44 { KERN_PANIC, "panic" }, 40 { KERN_PANIC, "panic" },
45 { KERN_REALROOTDEV, "real-root-dev" }, 41 { KERN_REALROOTDEV, "real-root-dev" },
46 42
@@ -1498,9 +1494,6 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
1498 (table->strategy == sysctl_ms_jiffies) || 1494 (table->strategy == sysctl_ms_jiffies) ||
1499 (table->proc_handler == proc_dostring) || 1495 (table->proc_handler == proc_dostring) ||
1500 (table->proc_handler == proc_dointvec) || 1496 (table->proc_handler == proc_dointvec) ||
1501#ifdef CONFIG_SECURITY_CAPABILITIES
1502 (table->proc_handler == proc_dointvec_bset) ||
1503#endif /* def CONFIG_SECURITY_CAPABILITIES */
1504 (table->proc_handler == proc_dointvec_minmax) || 1497 (table->proc_handler == proc_dointvec_minmax) ||
1505 (table->proc_handler == proc_dointvec_jiffies) || 1498 (table->proc_handler == proc_dointvec_jiffies) ||
1506 (table->proc_handler == proc_dointvec_userhz_jiffies) || 1499 (table->proc_handler == proc_dointvec_userhz_jiffies) ||
diff --git a/security/commoncap.c b/security/commoncap.c
index 01ab47845dcf..5aba82679a0b 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -25,20 +25,6 @@
25#include <linux/mount.h> 25#include <linux/mount.h>
26#include <linux/sched.h> 26#include <linux/sched.h>
27 27
28#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
29/*
30 * Because of the reduced scope of CAP_SETPCAP when filesystem
31 * capabilities are in effect, it is safe to allow this capability to
32 * be available in the default configuration.
33 */
34# define CAP_INIT_BSET CAP_FULL_SET
35#else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */
36# define CAP_INIT_BSET CAP_INIT_EFF_SET
37#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
38
39kernel_cap_t cap_bset = CAP_INIT_BSET; /* systemwide capability bound */
40EXPORT_SYMBOL(cap_bset);
41
42/* Global security state */ 28/* Global security state */
43 29
44unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ 30unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
@@ -140,6 +126,12 @@ int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
140 /* incapable of using this inheritable set */ 126 /* incapable of using this inheritable set */
141 return -EPERM; 127 return -EPERM;
142 } 128 }
129 if (!cap_issubset(*inheritable,
130 cap_combine(target->cap_inheritable,
131 current->cap_bset))) {
132 /* no new pI capabilities outside bounding set */
133 return -EPERM;
134 }
143 135
144 /* verify restrictions on target's new Permitted set */ 136 /* verify restrictions on target's new Permitted set */
145 if (!cap_issubset (*permitted, 137 if (!cap_issubset (*permitted,
@@ -337,10 +329,11 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
337 /* Derived from fs/exec.c:compute_creds. */ 329 /* Derived from fs/exec.c:compute_creds. */
338 kernel_cap_t new_permitted, working; 330 kernel_cap_t new_permitted, working;
339 331
340 new_permitted = cap_intersect (bprm->cap_permitted, cap_bset); 332 new_permitted = cap_intersect(bprm->cap_permitted,
341 working = cap_intersect (bprm->cap_inheritable, 333 current->cap_bset);
334 working = cap_intersect(bprm->cap_inheritable,
342 current->cap_inheritable); 335 current->cap_inheritable);
343 new_permitted = cap_combine (new_permitted, working); 336 new_permitted = cap_combine(new_permitted, working);
344 337
345 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 338 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
346 !cap_issubset (new_permitted, current->cap_permitted)) { 339 !cap_issubset (new_permitted, current->cap_permitted)) {
@@ -581,6 +574,23 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,
581 574
582 return -EPERM; 575 return -EPERM;
583} 576}
577
578/*
579 * called from kernel/sys.c for prctl(PR_CABSET_DROP)
580 * done without task_capability_lock() because it introduces
581 * no new races - i.e. only another task doing capget() on
582 * this task could get inconsistent info. There can be no
583 * racing writer bc a task can only change its own caps.
584 */
585long cap_prctl_drop(unsigned long cap)
586{
587 if (!capable(CAP_SETPCAP))
588 return -EPERM;
589 if (!cap_valid(cap))
590 return -EINVAL;
591 cap_lower(current->cap_bset, cap);
592 return 0;
593}
584#else 594#else
585int cap_task_setscheduler (struct task_struct *p, int policy, 595int cap_task_setscheduler (struct task_struct *p, int policy,
586 struct sched_param *lp) 596 struct sched_param *lp)