diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2009-01-14 08:14:02 -0500 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2009-01-14 08:15:18 -0500 |
commit | 6673e0c3fbeaed2cd08e2fd4a4aa97382d6fedb0 (patch) | |
tree | eb33a94f5e4b0e035001f7c96ef44cade0fbb489 | |
parent | ed6bb6194350dc6ae97a65dbf2d621a3dbe6bbe9 (diff) |
[CVE-2009-0029] System call wrapper special cases
System calls with an unsigned long long argument can't be converted with
the standard wrappers since that would include a cast to long, which in
turn means that we would lose the upper 32 bit on 32 bit architectures.
Also semctl can't use the standard wrapper since it has a 'union'
parameter.
So we handle them as special case and add some extra wrappers instead.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
-rw-r--r-- | fs/dcookies.c | 10 | ||||
-rw-r--r-- | fs/open.c | 27 | ||||
-rw-r--r-- | fs/read_write.c | 24 | ||||
-rw-r--r-- | fs/sync.c | 26 | ||||
-rw-r--r-- | ipc/sem.c | 9 | ||||
-rw-r--r-- | mm/fadvise.c | 18 | ||||
-rw-r--r-- | mm/filemap.c | 9 |
7 files changed, 106 insertions, 17 deletions
diff --git a/fs/dcookies.c b/fs/dcookies.c index 180e9fec4ad8..a21cabdbd87b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c | |||
@@ -145,7 +145,7 @@ out: | |||
145 | /* And here is where the userspace process can look up the cookie value | 145 | /* And here is where the userspace process can look up the cookie value |
146 | * to retrieve the path. | 146 | * to retrieve the path. |
147 | */ | 147 | */ |
148 | asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len) | 148 | SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) |
149 | { | 149 | { |
150 | unsigned long cookie = (unsigned long)cookie64; | 150 | unsigned long cookie = (unsigned long)cookie64; |
151 | int err = -EINVAL; | 151 | int err = -EINVAL; |
@@ -198,7 +198,13 @@ out: | |||
198 | mutex_unlock(&dcookie_mutex); | 198 | mutex_unlock(&dcookie_mutex); |
199 | return err; | 199 | return err; |
200 | } | 200 | } |
201 | 201 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | |
202 | asmlinkage long SyS_lookup_dcookie(u64 cookie64, long buf, long len) | ||
203 | { | ||
204 | return SYSC_lookup_dcookie(cookie64, (char __user *) buf, (size_t) len); | ||
205 | } | ||
206 | SYSCALL_ALIAS(sys_lookup_dcookie, SyS_lookup_dcookie); | ||
207 | #endif | ||
202 | 208 | ||
203 | static int dcookie_init(void) | 209 | static int dcookie_init(void) |
204 | { | 210 | { |
@@ -351,21 +351,35 @@ asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length) | |||
351 | 351 | ||
352 | /* LFS versions of truncate are only needed on 32 bit machines */ | 352 | /* LFS versions of truncate are only needed on 32 bit machines */ |
353 | #if BITS_PER_LONG == 32 | 353 | #if BITS_PER_LONG == 32 |
354 | asmlinkage long sys_truncate64(const char __user * path, loff_t length) | 354 | SYSCALL_DEFINE(truncate64)(const char __user * path, loff_t length) |
355 | { | 355 | { |
356 | return do_sys_truncate(path, length); | 356 | return do_sys_truncate(path, length); |
357 | } | 357 | } |
358 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
359 | asmlinkage long SyS_truncate64(long path, loff_t length) | ||
360 | { | ||
361 | return SYSC_truncate64((const char __user *) path, length); | ||
362 | } | ||
363 | SYSCALL_ALIAS(sys_truncate64, SyS_truncate64); | ||
364 | #endif | ||
358 | 365 | ||
359 | asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length) | 366 | SYSCALL_DEFINE(ftruncate64)(unsigned int fd, loff_t length) |
360 | { | 367 | { |
361 | long ret = do_sys_ftruncate(fd, length, 0); | 368 | long ret = do_sys_ftruncate(fd, length, 0); |
362 | /* avoid REGPARM breakage on x86: */ | 369 | /* avoid REGPARM breakage on x86: */ |
363 | asmlinkage_protect(2, ret, fd, length); | 370 | asmlinkage_protect(2, ret, fd, length); |
364 | return ret; | 371 | return ret; |
365 | } | 372 | } |
373 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
374 | asmlinkage long SyS_ftruncate64(long fd, loff_t length) | ||
375 | { | ||
376 | return SYSC_ftruncate64((unsigned int) fd, length); | ||
377 | } | ||
378 | SYSCALL_ALIAS(sys_ftruncate64, SyS_ftruncate64); | ||
366 | #endif | 379 | #endif |
380 | #endif /* BITS_PER_LONG == 32 */ | ||
367 | 381 | ||
368 | asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len) | 382 | SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) |
369 | { | 383 | { |
370 | struct file *file; | 384 | struct file *file; |
371 | struct inode *inode; | 385 | struct inode *inode; |
@@ -422,6 +436,13 @@ out_fput: | |||
422 | out: | 436 | out: |
423 | return ret; | 437 | return ret; |
424 | } | 438 | } |
439 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
440 | asmlinkage long SyS_fallocate(long fd, long mode, loff_t offset, loff_t len) | ||
441 | { | ||
442 | return SYSC_fallocate((int)fd, (int)mode, offset, len); | ||
443 | } | ||
444 | SYSCALL_ALIAS(sys_fallocate, SyS_fallocate); | ||
445 | #endif | ||
425 | 446 | ||
426 | /* | 447 | /* |
427 | * access() needs to use the real uid/gid, not the effective uid/gid. | 448 | * access() needs to use the real uid/gid, not the effective uid/gid. |
diff --git a/fs/read_write.c b/fs/read_write.c index 940367f51f2a..7a8326bc5903 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -403,8 +403,8 @@ asmlinkage long sys_write(unsigned int fd, const char __user * buf, size_t count | |||
403 | return ret; | 403 | return ret; |
404 | } | 404 | } |
405 | 405 | ||
406 | asmlinkage long sys_pread64(unsigned int fd, char __user *buf, | 406 | SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf, |
407 | size_t count, loff_t pos) | 407 | size_t count, loff_t pos) |
408 | { | 408 | { |
409 | struct file *file; | 409 | struct file *file; |
410 | ssize_t ret = -EBADF; | 410 | ssize_t ret = -EBADF; |
@@ -423,9 +423,17 @@ asmlinkage long sys_pread64(unsigned int fd, char __user *buf, | |||
423 | 423 | ||
424 | return ret; | 424 | return ret; |
425 | } | 425 | } |
426 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
427 | asmlinkage long SyS_pread64(long fd, long buf, long count, loff_t pos) | ||
428 | { | ||
429 | return SYSC_pread64((unsigned int) fd, (char __user *) buf, | ||
430 | (size_t) count, pos); | ||
431 | } | ||
432 | SYSCALL_ALIAS(sys_pread64, SyS_pread64); | ||
433 | #endif | ||
426 | 434 | ||
427 | asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, | 435 | SYSCALL_DEFINE(pwrite64)(unsigned int fd, const char __user *buf, |
428 | size_t count, loff_t pos) | 436 | size_t count, loff_t pos) |
429 | { | 437 | { |
430 | struct file *file; | 438 | struct file *file; |
431 | ssize_t ret = -EBADF; | 439 | ssize_t ret = -EBADF; |
@@ -444,6 +452,14 @@ asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, | |||
444 | 452 | ||
445 | return ret; | 453 | return ret; |
446 | } | 454 | } |
455 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
456 | asmlinkage long SyS_pwrite64(long fd, long buf, long count, loff_t pos) | ||
457 | { | ||
458 | return SYSC_pwrite64((unsigned int) fd, (const char __user *) buf, | ||
459 | (size_t) count, pos); | ||
460 | } | ||
461 | SYSCALL_ALIAS(sys_pwrite64, SyS_pwrite64); | ||
462 | #endif | ||
447 | 463 | ||
448 | /* | 464 | /* |
449 | * Reduce an iovec's length in-place. Return the resulting number of segments | 465 | * Reduce an iovec's length in-place. Return the resulting number of segments |
@@ -201,8 +201,8 @@ asmlinkage long sys_fdatasync(unsigned int fd) | |||
201 | * already-instantiated disk blocks, there are no guarantees here that the data | 201 | * already-instantiated disk blocks, there are no guarantees here that the data |
202 | * will be available after a crash. | 202 | * will be available after a crash. |
203 | */ | 203 | */ |
204 | asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, | 204 | SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, |
205 | unsigned int flags) | 205 | unsigned int flags) |
206 | { | 206 | { |
207 | int ret; | 207 | int ret; |
208 | struct file *file; | 208 | struct file *file; |
@@ -262,14 +262,32 @@ out_put: | |||
262 | out: | 262 | out: |
263 | return ret; | 263 | return ret; |
264 | } | 264 | } |
265 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
266 | asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes, | ||
267 | long flags) | ||
268 | { | ||
269 | return SYSC_sync_file_range((int) fd, offset, nbytes, | ||
270 | (unsigned int) flags); | ||
271 | } | ||
272 | SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range); | ||
273 | #endif | ||
265 | 274 | ||
266 | /* It would be nice if people remember that not all the world's an i386 | 275 | /* It would be nice if people remember that not all the world's an i386 |
267 | when they introduce new system calls */ | 276 | when they introduce new system calls */ |
268 | asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, | 277 | SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags, |
269 | loff_t offset, loff_t nbytes) | 278 | loff_t offset, loff_t nbytes) |
270 | { | 279 | { |
271 | return sys_sync_file_range(fd, offset, nbytes, flags); | 280 | return sys_sync_file_range(fd, offset, nbytes, flags); |
272 | } | 281 | } |
282 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
283 | asmlinkage long SyS_sync_file_range2(long fd, long flags, | ||
284 | loff_t offset, loff_t nbytes) | ||
285 | { | ||
286 | return SYSC_sync_file_range2((int) fd, (unsigned int) flags, | ||
287 | offset, nbytes); | ||
288 | } | ||
289 | SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2); | ||
290 | #endif | ||
273 | 291 | ||
274 | /* | 292 | /* |
275 | * `endbyte' is inclusive | 293 | * `endbyte' is inclusive |
@@ -887,7 +887,7 @@ out_up: | |||
887 | return err; | 887 | return err; |
888 | } | 888 | } |
889 | 889 | ||
890 | asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | 890 | SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg) |
891 | { | 891 | { |
892 | int err = -EINVAL; | 892 | int err = -EINVAL; |
893 | int version; | 893 | int version; |
@@ -923,6 +923,13 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | |||
923 | return -EINVAL; | 923 | return -EINVAL; |
924 | } | 924 | } |
925 | } | 925 | } |
926 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
927 | asmlinkage long SyS_semctl(int semid, int semnum, int cmd, union semun arg) | ||
928 | { | ||
929 | return SYSC_semctl((int) semid, (int) semnum, (int) cmd, arg); | ||
930 | } | ||
931 | SYSCALL_ALIAS(sys_semctl, SyS_semctl); | ||
932 | #endif | ||
926 | 933 | ||
927 | /* If the task doesn't already have a undo_list, then allocate one | 934 | /* If the task doesn't already have a undo_list, then allocate one |
928 | * here. We guarantee there is only one thread using this undo list, | 935 | * here. We guarantee there is only one thread using this undo list, |
diff --git a/mm/fadvise.c b/mm/fadvise.c index a1da969bd980..54a0f8040afa 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could | 24 | * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could |
25 | * deactivate the pages and clear PG_Referenced. | 25 | * deactivate the pages and clear PG_Referenced. |
26 | */ | 26 | */ |
27 | asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) | 27 | SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) |
28 | { | 28 | { |
29 | struct file *file = fget(fd); | 29 | struct file *file = fget(fd); |
30 | struct address_space *mapping; | 30 | struct address_space *mapping; |
@@ -126,12 +126,26 @@ out: | |||
126 | fput(file); | 126 | fput(file); |
127 | return ret; | 127 | return ret; |
128 | } | 128 | } |
129 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
130 | asmlinkage long SyS_fadvise64_64(long fd, loff_t offset, loff_t len, long advice) | ||
131 | { | ||
132 | return SYSC_fadvise64_64((int) fd, offset, len, (int) advice); | ||
133 | } | ||
134 | SYSCALL_ALIAS(sys_fadvise64_64, SyS_fadvise64_64); | ||
135 | #endif | ||
129 | 136 | ||
130 | #ifdef __ARCH_WANT_SYS_FADVISE64 | 137 | #ifdef __ARCH_WANT_SYS_FADVISE64 |
131 | 138 | ||
132 | asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) | 139 | SYSCALL_DEFINE(fadvise64)(int fd, loff_t offset, size_t len, int advice) |
133 | { | 140 | { |
134 | return sys_fadvise64_64(fd, offset, len, advice); | 141 | return sys_fadvise64_64(fd, offset, len, advice); |
135 | } | 142 | } |
143 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
144 | asmlinkage long SyS_fadvise64(long fd, loff_t offset, long len, long advice) | ||
145 | { | ||
146 | return SYSC_fadvise64((int) fd, offset, (size_t)len, (int)advice); | ||
147 | } | ||
148 | SYSCALL_ALIAS(sys_fadvise64, SyS_fadvise64); | ||
149 | #endif | ||
136 | 150 | ||
137 | #endif | 151 | #endif |
diff --git a/mm/filemap.c b/mm/filemap.c index 538b75ed6236..23acefe51808 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1374,7 +1374,7 @@ do_readahead(struct address_space *mapping, struct file *filp, | |||
1374 | return 0; | 1374 | return 0; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | asmlinkage long sys_readahead(int fd, loff_t offset, size_t count) | 1377 | SYSCALL_DEFINE(readahead)(int fd, loff_t offset, size_t count) |
1378 | { | 1378 | { |
1379 | ssize_t ret; | 1379 | ssize_t ret; |
1380 | struct file *file; | 1380 | struct file *file; |
@@ -1393,6 +1393,13 @@ asmlinkage long sys_readahead(int fd, loff_t offset, size_t count) | |||
1393 | } | 1393 | } |
1394 | return ret; | 1394 | return ret; |
1395 | } | 1395 | } |
1396 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
1397 | asmlinkage long SyS_readahead(long fd, loff_t offset, long count) | ||
1398 | { | ||
1399 | return SYSC_readahead((int) fd, offset, (size_t) count); | ||
1400 | } | ||
1401 | SYSCALL_ALIAS(sys_readahead, SyS_readahead); | ||
1402 | #endif | ||
1396 | 1403 | ||
1397 | #ifdef CONFIG_MMU | 1404 | #ifdef CONFIG_MMU |
1398 | /** | 1405 | /** |