diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/capability.c | 111 | ||||
-rw-r--r-- | kernel/cpuset.c | 10 | ||||
-rw-r--r-- | kernel/kgdb.c | 16 | ||||
-rw-r--r-- | kernel/kprobes.c | 15 | ||||
-rw-r--r-- | kernel/sched.c | 22 |
5 files changed, 109 insertions, 65 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 39e8193b41ea..cfbe44299488 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -53,6 +53,69 @@ static void warn_legacy_capability_use(void) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * Version 2 capabilities worked fine, but the linux/capability.h file | ||
57 | * that accompanied their introduction encouraged their use without | ||
58 | * the necessary user-space source code changes. As such, we have | ||
59 | * created a version 3 with equivalent functionality to version 2, but | ||
60 | * with a header change to protect legacy source code from using | ||
61 | * version 2 when it wanted to use version 1. If your system has code | ||
62 | * that trips the following warning, it is using version 2 specific | ||
63 | * capabilities and may be doing so insecurely. | ||
64 | * | ||
65 | * The remedy is to either upgrade your version of libcap (to 2.10+, | ||
66 | * if the application is linked against it), or recompile your | ||
67 | * application with modern kernel headers and this warning will go | ||
68 | * away. | ||
69 | */ | ||
70 | |||
71 | static void warn_deprecated_v2(void) | ||
72 | { | ||
73 | static int warned; | ||
74 | |||
75 | if (!warned) { | ||
76 | char name[sizeof(current->comm)]; | ||
77 | |||
78 | printk(KERN_INFO "warning: `%s' uses deprecated v2" | ||
79 | " capabilities in a way that may be insecure.\n", | ||
80 | get_task_comm(name, current)); | ||
81 | warned = 1; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Version check. Return the number of u32s in each capability flag | ||
87 | * array, or a negative value on error. | ||
88 | */ | ||
89 | static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) | ||
90 | { | ||
91 | __u32 version; | ||
92 | |||
93 | if (get_user(version, &header->version)) | ||
94 | return -EFAULT; | ||
95 | |||
96 | switch (version) { | ||
97 | case _LINUX_CAPABILITY_VERSION_1: | ||
98 | warn_legacy_capability_use(); | ||
99 | *tocopy = _LINUX_CAPABILITY_U32S_1; | ||
100 | break; | ||
101 | case _LINUX_CAPABILITY_VERSION_2: | ||
102 | warn_deprecated_v2(); | ||
103 | /* | ||
104 | * fall through - v3 is otherwise equivalent to v2. | ||
105 | */ | ||
106 | case _LINUX_CAPABILITY_VERSION_3: | ||
107 | *tocopy = _LINUX_CAPABILITY_U32S_3; | ||
108 | break; | ||
109 | default: | ||
110 | if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version)) | ||
111 | return -EFAULT; | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | /* | ||
56 | * For sys_getproccap() and sys_setproccap(), any of the three | 119 | * For sys_getproccap() and sys_setproccap(), any of the three |
57 | * capability set pointers may be NULL -- indicating that that set is | 120 | * capability set pointers may be NULL -- indicating that that set is |
58 | * uninteresting and/or not to be changed. | 121 | * uninteresting and/or not to be changed. |
@@ -71,27 +134,13 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) | |||
71 | { | 134 | { |
72 | int ret = 0; | 135 | int ret = 0; |
73 | pid_t pid; | 136 | pid_t pid; |
74 | __u32 version; | ||
75 | struct task_struct *target; | 137 | struct task_struct *target; |
76 | unsigned tocopy; | 138 | unsigned tocopy; |
77 | kernel_cap_t pE, pI, pP; | 139 | kernel_cap_t pE, pI, pP; |
78 | 140 | ||
79 | if (get_user(version, &header->version)) | 141 | ret = cap_validate_magic(header, &tocopy); |
80 | return -EFAULT; | 142 | if (ret != 0) |
81 | 143 | return ret; | |
82 | switch (version) { | ||
83 | case _LINUX_CAPABILITY_VERSION_1: | ||
84 | warn_legacy_capability_use(); | ||
85 | tocopy = _LINUX_CAPABILITY_U32S_1; | ||
86 | break; | ||
87 | case _LINUX_CAPABILITY_VERSION_2: | ||
88 | tocopy = _LINUX_CAPABILITY_U32S_2; | ||
89 | break; | ||
90 | default: | ||
91 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) | ||
92 | return -EFAULT; | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | 144 | ||
96 | if (get_user(pid, &header->pid)) | 145 | if (get_user(pid, &header->pid)) |
97 | return -EFAULT; | 146 | return -EFAULT; |
@@ -118,7 +167,7 @@ out: | |||
118 | spin_unlock(&task_capability_lock); | 167 | spin_unlock(&task_capability_lock); |
119 | 168 | ||
120 | if (!ret) { | 169 | if (!ret) { |
121 | struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S]; | 170 | struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; |
122 | unsigned i; | 171 | unsigned i; |
123 | 172 | ||
124 | for (i = 0; i < tocopy; i++) { | 173 | for (i = 0; i < tocopy; i++) { |
@@ -128,7 +177,7 @@ out: | |||
128 | } | 177 | } |
129 | 178 | ||
130 | /* | 179 | /* |
131 | * Note, in the case, tocopy < _LINUX_CAPABILITY_U32S, | 180 | * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, |
132 | * we silently drop the upper capabilities here. This | 181 | * we silently drop the upper capabilities here. This |
133 | * has the effect of making older libcap | 182 | * has the effect of making older libcap |
134 | * implementations implicitly drop upper capability | 183 | * implementations implicitly drop upper capability |
@@ -240,30 +289,16 @@ static inline int cap_set_all(kernel_cap_t *effective, | |||
240 | */ | 289 | */ |
241 | asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) | 290 | asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) |
242 | { | 291 | { |
243 | struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S]; | 292 | struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; |
244 | unsigned i, tocopy; | 293 | unsigned i, tocopy; |
245 | kernel_cap_t inheritable, permitted, effective; | 294 | kernel_cap_t inheritable, permitted, effective; |
246 | __u32 version; | ||
247 | struct task_struct *target; | 295 | struct task_struct *target; |
248 | int ret; | 296 | int ret; |
249 | pid_t pid; | 297 | pid_t pid; |
250 | 298 | ||
251 | if (get_user(version, &header->version)) | 299 | ret = cap_validate_magic(header, &tocopy); |
252 | return -EFAULT; | 300 | if (ret != 0) |
253 | 301 | return ret; | |
254 | switch (version) { | ||
255 | case _LINUX_CAPABILITY_VERSION_1: | ||
256 | warn_legacy_capability_use(); | ||
257 | tocopy = _LINUX_CAPABILITY_U32S_1; | ||
258 | break; | ||
259 | case _LINUX_CAPABILITY_VERSION_2: | ||
260 | tocopy = _LINUX_CAPABILITY_U32S_2; | ||
261 | break; | ||
262 | default: | ||
263 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) | ||
264 | return -EFAULT; | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | 302 | ||
268 | if (get_user(pid, &header->pid)) | 303 | if (get_user(pid, &header->pid)) |
269 | return -EFAULT; | 304 | return -EFAULT; |
@@ -281,7 +316,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) | |||
281 | permitted.cap[i] = kdata[i].permitted; | 316 | permitted.cap[i] = kdata[i].permitted; |
282 | inheritable.cap[i] = kdata[i].inheritable; | 317 | inheritable.cap[i] = kdata[i].inheritable; |
283 | } | 318 | } |
284 | while (i < _LINUX_CAPABILITY_U32S) { | 319 | while (i < _KERNEL_CAPABILITY_U32S) { |
285 | effective.cap[i] = 0; | 320 | effective.cap[i] = 0; |
286 | permitted.cap[i] = 0; | 321 | permitted.cap[i] = 0; |
287 | inheritable.cap[i] = 0; | 322 | inheritable.cap[i] = 0; |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 86ea9e34e326..039baa4cd90c 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -797,8 +797,10 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
797 | retval = cpulist_parse(buf, trialcs.cpus_allowed); | 797 | retval = cpulist_parse(buf, trialcs.cpus_allowed); |
798 | if (retval < 0) | 798 | if (retval < 0) |
799 | return retval; | 799 | return retval; |
800 | |||
801 | if (!cpus_subset(trialcs.cpus_allowed, cpu_online_map)) | ||
802 | return -EINVAL; | ||
800 | } | 803 | } |
801 | cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map); | ||
802 | retval = validate_change(cs, &trialcs); | 804 | retval = validate_change(cs, &trialcs); |
803 | if (retval < 0) | 805 | if (retval < 0) |
804 | return retval; | 806 | return retval; |
@@ -932,9 +934,11 @@ static int update_nodemask(struct cpuset *cs, char *buf) | |||
932 | retval = nodelist_parse(buf, trialcs.mems_allowed); | 934 | retval = nodelist_parse(buf, trialcs.mems_allowed); |
933 | if (retval < 0) | 935 | if (retval < 0) |
934 | goto done; | 936 | goto done; |
937 | |||
938 | if (!nodes_subset(trialcs.mems_allowed, | ||
939 | node_states[N_HIGH_MEMORY])) | ||
940 | return -EINVAL; | ||
935 | } | 941 | } |
936 | nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, | ||
937 | node_states[N_HIGH_MEMORY]); | ||
938 | oldmem = cs->mems_allowed; | 942 | oldmem = cs->mems_allowed; |
939 | if (nodes_equal(oldmem, trialcs.mems_allowed)) { | 943 | if (nodes_equal(oldmem, trialcs.mems_allowed)) { |
940 | retval = 0; /* Too easy - nothing to do */ | 944 | retval = 0; /* Too easy - nothing to do */ |
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 14787de568b3..79e3c90113c2 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <asm/byteorder.h> | 52 | #include <asm/byteorder.h> |
53 | #include <asm/atomic.h> | 53 | #include <asm/atomic.h> |
54 | #include <asm/system.h> | 54 | #include <asm/system.h> |
55 | #include <asm/unaligned.h> | ||
55 | 56 | ||
56 | static int kgdb_break_asap; | 57 | static int kgdb_break_asap; |
57 | 58 | ||
@@ -227,8 +228,6 @@ void __weak kgdb_disable_hw_debug(struct pt_regs *regs) | |||
227 | * GDB remote protocol parser: | 228 | * GDB remote protocol parser: |
228 | */ | 229 | */ |
229 | 230 | ||
230 | static const char hexchars[] = "0123456789abcdef"; | ||
231 | |||
232 | static int hex(char ch) | 231 | static int hex(char ch) |
233 | { | 232 | { |
234 | if ((ch >= 'a') && (ch <= 'f')) | 233 | if ((ch >= 'a') && (ch <= 'f')) |
@@ -316,8 +315,8 @@ static void put_packet(char *buffer) | |||
316 | } | 315 | } |
317 | 316 | ||
318 | kgdb_io_ops->write_char('#'); | 317 | kgdb_io_ops->write_char('#'); |
319 | kgdb_io_ops->write_char(hexchars[checksum >> 4]); | 318 | kgdb_io_ops->write_char(hex_asc_hi(checksum)); |
320 | kgdb_io_ops->write_char(hexchars[checksum & 0xf]); | 319 | kgdb_io_ops->write_char(hex_asc_lo(checksum)); |
321 | if (kgdb_io_ops->flush) | 320 | if (kgdb_io_ops->flush) |
322 | kgdb_io_ops->flush(); | 321 | kgdb_io_ops->flush(); |
323 | 322 | ||
@@ -478,8 +477,8 @@ static void error_packet(char *pkt, int error) | |||
478 | { | 477 | { |
479 | error = -error; | 478 | error = -error; |
480 | pkt[0] = 'E'; | 479 | pkt[0] = 'E'; |
481 | pkt[1] = hexchars[(error / 10)]; | 480 | pkt[1] = hex_asc[(error / 10)]; |
482 | pkt[2] = hexchars[(error % 10)]; | 481 | pkt[2] = hex_asc[(error % 10)]; |
483 | pkt[3] = '\0'; | 482 | pkt[3] = '\0'; |
484 | } | 483 | } |
485 | 484 | ||
@@ -510,10 +509,7 @@ static void int_to_threadref(unsigned char *id, int value) | |||
510 | scan = (unsigned char *)id; | 509 | scan = (unsigned char *)id; |
511 | while (i--) | 510 | while (i--) |
512 | *scan++ = 0; | 511 | *scan++ = 0; |
513 | *scan++ = (value >> 24) & 0xff; | 512 | put_unaligned_be32(value, scan); |
514 | *scan++ = (value >> 16) & 0xff; | ||
515 | *scan++ = (value >> 8) & 0xff; | ||
516 | *scan++ = (value & 0xff); | ||
517 | } | 513 | } |
518 | 514 | ||
519 | static struct task_struct *getthread(struct pt_regs *regs, int tid) | 515 | static struct task_struct *getthread(struct pt_regs *regs, int tid) |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 1e0250cb9486..d4998f81e229 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -699,8 +699,9 @@ static int __register_kprobes(struct kprobe **kps, int num, | |||
699 | return -EINVAL; | 699 | return -EINVAL; |
700 | for (i = 0; i < num; i++) { | 700 | for (i = 0; i < num; i++) { |
701 | ret = __register_kprobe(kps[i], called_from); | 701 | ret = __register_kprobe(kps[i], called_from); |
702 | if (ret < 0 && i > 0) { | 702 | if (ret < 0) { |
703 | unregister_kprobes(kps, i); | 703 | if (i > 0) |
704 | unregister_kprobes(kps, i); | ||
704 | break; | 705 | break; |
705 | } | 706 | } |
706 | } | 707 | } |
@@ -776,8 +777,9 @@ static int __register_jprobes(struct jprobe **jps, int num, | |||
776 | jp->kp.break_handler = longjmp_break_handler; | 777 | jp->kp.break_handler = longjmp_break_handler; |
777 | ret = __register_kprobe(&jp->kp, called_from); | 778 | ret = __register_kprobe(&jp->kp, called_from); |
778 | } | 779 | } |
779 | if (ret < 0 && i > 0) { | 780 | if (ret < 0) { |
780 | unregister_jprobes(jps, i); | 781 | if (i > 0) |
782 | unregister_jprobes(jps, i); | ||
781 | break; | 783 | break; |
782 | } | 784 | } |
783 | } | 785 | } |
@@ -920,8 +922,9 @@ static int __register_kretprobes(struct kretprobe **rps, int num, | |||
920 | return -EINVAL; | 922 | return -EINVAL; |
921 | for (i = 0; i < num; i++) { | 923 | for (i = 0; i < num; i++) { |
922 | ret = __register_kretprobe(rps[i], called_from); | 924 | ret = __register_kretprobe(rps[i], called_from); |
923 | if (ret < 0 && i > 0) { | 925 | if (ret < 0) { |
924 | unregister_kretprobes(rps, i); | 926 | if (i > 0) |
927 | unregister_kretprobes(rps, i); | ||
925 | break; | 928 | break; |
926 | } | 929 | } |
927 | } | 930 | } |
diff --git a/kernel/sched.c b/kernel/sched.c index bfb8ad8ed171..eaf6751e7612 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -312,12 +312,15 @@ static DEFINE_SPINLOCK(task_group_lock); | |||
312 | #endif | 312 | #endif |
313 | 313 | ||
314 | /* | 314 | /* |
315 | * A weight of 0, 1 or ULONG_MAX can cause arithmetics problems. | 315 | * A weight of 0 or 1 can cause arithmetics problems. |
316 | * A weight of a cfs_rq is the sum of weights of which entities | ||
317 | * are queued on this cfs_rq, so a weight of a entity should not be | ||
318 | * too large, so as the shares value of a task group. | ||
316 | * (The default weight is 1024 - so there's no practical | 319 | * (The default weight is 1024 - so there's no practical |
317 | * limitation from this.) | 320 | * limitation from this.) |
318 | */ | 321 | */ |
319 | #define MIN_SHARES 2 | 322 | #define MIN_SHARES 2 |
320 | #define MAX_SHARES (ULONG_MAX - 1) | 323 | #define MAX_SHARES (1UL << 18) |
321 | 324 | ||
322 | static int init_task_group_load = INIT_TASK_GROUP_LOAD; | 325 | static int init_task_group_load = INIT_TASK_GROUP_LOAD; |
323 | #endif | 326 | #endif |
@@ -1337,8 +1340,13 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight, | |||
1337 | { | 1340 | { |
1338 | u64 tmp; | 1341 | u64 tmp; |
1339 | 1342 | ||
1340 | if (!lw->inv_weight) | 1343 | if (!lw->inv_weight) { |
1341 | lw->inv_weight = 1 + (WMULT_CONST-lw->weight/2)/(lw->weight+1); | 1344 | if (BITS_PER_LONG > 32 && unlikely(lw->weight >= WMULT_CONST)) |
1345 | lw->inv_weight = 1; | ||
1346 | else | ||
1347 | lw->inv_weight = 1 + (WMULT_CONST-lw->weight/2) | ||
1348 | / (lw->weight+1); | ||
1349 | } | ||
1342 | 1350 | ||
1343 | tmp = (u64)delta_exec * weight; | 1351 | tmp = (u64)delta_exec * weight; |
1344 | /* | 1352 | /* |
@@ -4159,12 +4167,10 @@ need_resched_nonpreemptible: | |||
4159 | clear_tsk_need_resched(prev); | 4167 | clear_tsk_need_resched(prev); |
4160 | 4168 | ||
4161 | if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { | 4169 | if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { |
4162 | if (unlikely((prev->state & TASK_INTERRUPTIBLE) && | 4170 | if (unlikely(signal_pending_state(prev->state, prev))) |
4163 | signal_pending(prev))) { | ||
4164 | prev->state = TASK_RUNNING; | 4171 | prev->state = TASK_RUNNING; |
4165 | } else { | 4172 | else |
4166 | deactivate_task(rq, prev, 1); | 4173 | deactivate_task(rq, prev, 1); |
4167 | } | ||
4168 | switch_count = &prev->nvcsw; | 4174 | switch_count = &prev->nvcsw; |
4169 | } | 4175 | } |
4170 | 4176 | ||