aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2007-08-22 17:01:28 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-08-22 22:52:45 -0400
commit34b4e4aa3c470ce8fa2bd78abb1741b4b58baad7 (patch)
tree91d620288f1aaf63c12dc84ca1015465818601f2
parentafe1ab4d577892822de2c8e803fbfaed6ec44ba3 (diff)
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>
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/security.h20
-rw-r--r--mm/mmap.c6
-rw-r--r--mm/nommu.c2
-rw-r--r--security/commoncap.c4
-rw-r--r--security/dummy.c4
-rw-r--r--security/selinux/hooks.c4
7 files changed, 26 insertions, 16 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 655094dc9440..1692dd6cb915 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1042,7 +1042,7 @@ static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
1042} 1042}
1043 1043
1044/* mmap.c */ 1044/* mmap.c */
1045extern int __vm_enough_memory(long pages, int cap_sys_admin); 1045extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
1046extern void vma_adjust(struct vm_area_struct *vma, unsigned long start, 1046extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
1047 unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert); 1047 unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert);
1048extern struct vm_area_struct *vma_merge(struct mm_struct *, 1048extern struct vm_area_struct *vma_merge(struct mm_struct *,
diff --git a/include/linux/security.h b/include/linux/security.h
index c11dc8aa0351..1a15526e9f67 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -54,7 +54,7 @@ extern int cap_inode_removexattr(struct dentry *dentry, char *name);
54extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); 54extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
55extern void cap_task_reparent_to_init (struct task_struct *p); 55extern void cap_task_reparent_to_init (struct task_struct *p);
56extern int cap_syslog (int type); 56extern int cap_syslog (int type);
57extern int cap_vm_enough_memory (long pages); 57extern int cap_vm_enough_memory (struct mm_struct *mm, long pages);
58 58
59struct msghdr; 59struct msghdr;
60struct sk_buff; 60struct sk_buff;
@@ -1125,6 +1125,7 @@ struct request_sock;
1125 * Return 0 if permission is granted. 1125 * Return 0 if permission is granted.
1126 * @vm_enough_memory: 1126 * @vm_enough_memory:
1127 * Check permissions for allocating a new virtual mapping. 1127 * Check permissions for allocating a new virtual mapping.
1128 * @mm contains the mm struct it is being added to.
1128 * @pages contains the number of pages. 1129 * @pages contains the number of pages.
1129 * Return 0 if permission is granted. 1130 * Return 0 if permission is granted.
1130 * 1131 *
@@ -1169,7 +1170,7 @@ struct security_operations {
1169 int (*quota_on) (struct dentry * dentry); 1170 int (*quota_on) (struct dentry * dentry);
1170 int (*syslog) (int type); 1171 int (*syslog) (int type);
1171 int (*settime) (struct timespec *ts, struct timezone *tz); 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 int (*bprm_alloc_security) (struct linux_binprm * bprm); 1175 int (*bprm_alloc_security) (struct linux_binprm * bprm);
1175 void (*bprm_free_security) (struct linux_binprm * bprm); 1176 void (*bprm_free_security) (struct linux_binprm * bprm);
@@ -1469,10 +1470,14 @@ static inline int security_settime(struct timespec *ts, struct timezone *tz)
1469 return security_ops->settime(ts, tz); 1470 return security_ops->settime(ts, tz);
1470} 1471}
1471 1472
1472
1473static inline int security_vm_enough_memory(long pages) 1473static 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}
1477
1478static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
1479{
1480 return security_ops->vm_enough_memory(mm, pages);
1476} 1481}
1477 1482
1478static inline int security_bprm_alloc (struct linux_binprm *bprm) 1483static inline int security_bprm_alloc (struct linux_binprm *bprm)
@@ -2219,7 +2224,12 @@ static inline int security_settime(struct timespec *ts, struct timezone *tz)
2219 2224
2220static inline int security_vm_enough_memory(long pages) 2225static 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
2230static 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
2225static inline int security_bprm_alloc (struct linux_binprm *bprm) 2235static inline int security_bprm_alloc (struct linux_binprm *bprm)
diff --git a/mm/mmap.c b/mm/mmap.c
index b6537211b9cc..0d40e66c841b 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -93,7 +93,7 @@ atomic_t vm_committed_space = ATOMIC_INIT(0);
93 * Note this is a helper function intended to be used by LSMs which 93 * Note this is a helper function intended to be used by LSMs which
94 * wish to use this logic. 94 * wish to use this logic.
95 */ 95 */
96int __vm_enough_memory(long pages, int cap_sys_admin) 96int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
97{ 97{
98 unsigned long free, allowed; 98 unsigned long free, allowed;
99 99
@@ -166,7 +166,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
166 166
167 /* Don't let a single process grow too big: 167 /* Don't let a single process grow too big:
168 leave 3% of the size of this process for other processes */ 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 * cast `allowed' as a signed long because vm_committed_space 172 * cast `allowed' as a signed long because vm_committed_space
@@ -2077,7 +2077,7 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
2077 if (__vma && __vma->vm_start < vma->vm_end) 2077 if (__vma && __vma->vm_start < vma->vm_end)
2078 return -ENOMEM; 2078 return -ENOMEM;
2079 if ((vma->vm_flags & VM_ACCOUNT) && 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 return -ENOMEM; 2081 return -ENOMEM;
2082 vma_link(mm, vma, prev, rb_link, rb_parent); 2082 vma_link(mm, vma, prev, rb_link, rb_parent);
2083 return 0; 2083 return 0;
diff --git a/mm/nommu.c b/mm/nommu.c
index 9eef6a398555..8ed0cb43118a 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1270,7 +1270,7 @@ EXPORT_SYMBOL(get_unmapped_area);
1270 * Note this is a helper function intended to be used by LSMs which 1270 * Note this is a helper function intended to be used by LSMs which
1271 * wish to use this logic. 1271 * wish to use this logic.
1272 */ 1272 */
1273int __vm_enough_memory(long pages, int cap_sys_admin) 1273int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
1274{ 1274{
1275 unsigned long free, allowed; 1275 unsigned long free, allowed;
1276 1276
diff --git a/security/commoncap.c b/security/commoncap.c
index 338606eb7238..7520361663e8 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -315,13 +315,13 @@ int cap_syslog (int type)
315 return 0; 315 return 0;
316} 316}
317 317
318int cap_vm_enough_memory(long pages) 318int cap_vm_enough_memory(struct mm_struct *mm, long pages)
319{ 319{
320 int cap_sys_admin = 0; 320 int cap_sys_admin = 0;
321 321
322 if (cap_capable(current, CAP_SYS_ADMIN) == 0) 322 if (cap_capable(current, CAP_SYS_ADMIN) == 0)
323 cap_sys_admin = 1; 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
327EXPORT_SYMBOL(cap_capable); 327EXPORT_SYMBOL(cap_capable);
diff --git a/security/dummy.c b/security/dummy.c
index 19d813d5e083..853ec2292798 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -108,13 +108,13 @@ static int dummy_settime(struct timespec *ts, struct timezone *tz)
108 return 0; 108 return 0;
109} 109}
110 110
111static int dummy_vm_enough_memory(long pages) 111static int dummy_vm_enough_memory(struct mm_struct *mm, long pages)
112{ 112{
113 int cap_sys_admin = 0; 113 int cap_sys_admin = 0;
114 114
115 if (dummy_capable(current, CAP_SYS_ADMIN) == 0) 115 if (dummy_capable(current, CAP_SYS_ADMIN) == 0)
116 cap_sys_admin = 1; 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
120static int dummy_bprm_alloc_security (struct linux_binprm *bprm) 120static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6237933f7d82..d8bc4172819c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1584,7 +1584,7 @@ static int selinux_syslog(int type)
1584 * Do not audit the selinux permission check, as this is applied to all 1584 * Do not audit the selinux permission check, as this is applied to all
1585 * processes that allocate mappings. 1585 * processes that allocate mappings.
1586 */ 1586 */
1587static int selinux_vm_enough_memory(long pages) 1587static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1588{ 1588{
1589 int rc, cap_sys_admin = 0; 1589 int rc, cap_sys_admin = 0;
1590 struct task_security_struct *tsec = current->security; 1590 struct task_security_struct *tsec = current->security;
@@ -1600,7 +1600,7 @@ static int selinux_vm_enough_memory(long pages)
1600 if (rc == 0) 1600 if (rc == 0)
1601 cap_sys_admin = 1; 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/* binprm security operations */ 1606/* binprm security operations */