Commit 34b4e4aa3c470ce8fa2bd78abb1741b4b58baad7

Authored by Alan Cox
Committed by Linus Torvalds
1 parent afe1ab4d57

fix NULL pointer dereference in __vm_enough_memory()

The new exec code inserts an accounted vma into an mm struct which is not
current->mm.  The existing memory check code has a hard coded assumption
that this does not happen as does the security code.

As the correct mm is known we pass the mm to the security method and the
helper function.  A new security test is added for the case where we need
to pass the mm and the existing one is modified to pass current->mm to
avoid the need to change large amounts of code.

(Thanks to Tobias for fixing rejects and testing)

Signed-off-by: Alan Cox <alan@redhat.com>
Cc: WU Fengguang <wfg@mail.ustc.edu.cn>
Cc: James Morris <jmorris@redhat.com>
Cc: Tobias Diedrich <ranma+kernel@tdiedrich.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 7 changed files with 26 additions and 16 deletions Side-by-side Diff

... ... @@ -1042,7 +1042,7 @@
1042 1042 }
1043 1043  
1044 1044 /* mmap.c */
1045   -extern int __vm_enough_memory(long pages, int cap_sys_admin);
  1045 +extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
1046 1046 extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
1047 1047 unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert);
1048 1048 extern struct vm_area_struct *vma_merge(struct mm_struct *,
include/linux/security.h
... ... @@ -54,7 +54,7 @@
54 54 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
55 55 extern void cap_task_reparent_to_init (struct task_struct *p);
56 56 extern int cap_syslog (int type);
57   -extern int cap_vm_enough_memory (long pages);
  57 +extern int cap_vm_enough_memory (struct mm_struct *mm, long pages);
58 58  
59 59 struct msghdr;
60 60 struct sk_buff;
... ... @@ -1125,6 +1125,7 @@
1125 1125 * Return 0 if permission is granted.
1126 1126 * @vm_enough_memory:
1127 1127 * Check permissions for allocating a new virtual mapping.
  1128 + * @mm contains the mm struct it is being added to.
1128 1129 * @pages contains the number of pages.
1129 1130 * Return 0 if permission is granted.
1130 1131 *
... ... @@ -1169,7 +1170,7 @@
1169 1170 int (*quota_on) (struct dentry * dentry);
1170 1171 int (*syslog) (int type);
1171 1172 int (*settime) (struct timespec *ts, struct timezone *tz);
1172   - int (*vm_enough_memory) (long pages);
  1173 + int (*vm_enough_memory) (struct mm_struct *mm, long pages);
1173 1174  
1174 1175 int (*bprm_alloc_security) (struct linux_binprm * bprm);
1175 1176 void (*bprm_free_security) (struct linux_binprm * bprm);
1176 1177  
1177 1178  
... ... @@ -1469,12 +1470,16 @@
1469 1470 return security_ops->settime(ts, tz);
1470 1471 }
1471 1472  
1472   -
1473 1473 static inline int security_vm_enough_memory(long pages)
1474 1474 {
1475   - return security_ops->vm_enough_memory(pages);
  1475 + return security_ops->vm_enough_memory(current->mm, pages);
1476 1476 }
1477 1477  
  1478 +static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
  1479 +{
  1480 + return security_ops->vm_enough_memory(mm, pages);
  1481 +}
  1482 +
1478 1483 static inline int security_bprm_alloc (struct linux_binprm *bprm)
1479 1484 {
1480 1485 return security_ops->bprm_alloc_security (bprm);
... ... @@ -2219,7 +2224,12 @@
2219 2224  
2220 2225 static inline int security_vm_enough_memory(long pages)
2221 2226 {
2222   - return cap_vm_enough_memory(pages);
  2227 + return cap_vm_enough_memory(current->mm, pages);
  2228 +}
  2229 +
  2230 +static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
  2231 +{
  2232 + return cap_vm_enough_memory(mm, pages);
2223 2233 }
2224 2234  
2225 2235 static inline int security_bprm_alloc (struct linux_binprm *bprm)
... ... @@ -93,7 +93,7 @@
93 93 * Note this is a helper function intended to be used by LSMs which
94 94 * wish to use this logic.
95 95 */
96   -int __vm_enough_memory(long pages, int cap_sys_admin)
  96 +int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
97 97 {
98 98 unsigned long free, allowed;
99 99  
... ... @@ -166,7 +166,7 @@
166 166  
167 167 /* Don't let a single process grow too big:
168 168 leave 3% of the size of this process for other processes */
169   - allowed -= current->mm->total_vm / 32;
  169 + allowed -= mm->total_vm / 32;
170 170  
171 171 /*
172 172 * cast `allowed' as a signed long because vm_committed_space
... ... @@ -2077,7 +2077,7 @@
2077 2077 if (__vma && __vma->vm_start < vma->vm_end)
2078 2078 return -ENOMEM;
2079 2079 if ((vma->vm_flags & VM_ACCOUNT) &&
2080   - security_vm_enough_memory(vma_pages(vma)))
  2080 + security_vm_enough_memory_mm(mm, vma_pages(vma)))
2081 2081 return -ENOMEM;
2082 2082 vma_link(mm, vma, prev, rb_link, rb_parent);
2083 2083 return 0;
... ... @@ -1270,7 +1270,7 @@
1270 1270 * Note this is a helper function intended to be used by LSMs which
1271 1271 * wish to use this logic.
1272 1272 */
1273   -int __vm_enough_memory(long pages, int cap_sys_admin)
  1273 +int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
1274 1274 {
1275 1275 unsigned long free, allowed;
1276 1276  
security/commoncap.c
... ... @@ -315,13 +315,13 @@
315 315 return 0;
316 316 }
317 317  
318   -int cap_vm_enough_memory(long pages)
  318 +int cap_vm_enough_memory(struct mm_struct *mm, long pages)
319 319 {
320 320 int cap_sys_admin = 0;
321 321  
322 322 if (cap_capable(current, CAP_SYS_ADMIN) == 0)
323 323 cap_sys_admin = 1;
324   - return __vm_enough_memory(pages, cap_sys_admin);
  324 + return __vm_enough_memory(mm, pages, cap_sys_admin);
325 325 }
326 326  
327 327 EXPORT_SYMBOL(cap_capable);
... ... @@ -108,13 +108,13 @@
108 108 return 0;
109 109 }
110 110  
111   -static int dummy_vm_enough_memory(long pages)
  111 +static int dummy_vm_enough_memory(struct mm_struct *mm, long pages)
112 112 {
113 113 int cap_sys_admin = 0;
114 114  
115 115 if (dummy_capable(current, CAP_SYS_ADMIN) == 0)
116 116 cap_sys_admin = 1;
117   - return __vm_enough_memory(pages, cap_sys_admin);
  117 + return __vm_enough_memory(mm, pages, cap_sys_admin);
118 118 }
119 119  
120 120 static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
security/selinux/hooks.c
... ... @@ -1584,7 +1584,7 @@
1584 1584 * Do not audit the selinux permission check, as this is applied to all
1585 1585 * processes that allocate mappings.
1586 1586 */
1587   -static int selinux_vm_enough_memory(long pages)
  1587 +static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1588 1588 {
1589 1589 int rc, cap_sys_admin = 0;
1590 1590 struct task_security_struct *tsec = current->security;
... ... @@ -1600,7 +1600,7 @@
1600 1600 if (rc == 0)
1601 1601 cap_sys_admin = 1;
1602 1602  
1603   - return __vm_enough_memory(pages, cap_sys_admin);
  1603 + return __vm_enough_memory(mm, pages, cap_sys_admin);
1604 1604 }
1605 1605  
1606 1606 /* binprm security operations */