Skip to content

Commit

Permalink
x86: don't allow tail-calls in sys_ftruncate[64]()
Browse files Browse the repository at this point in the history
Gcc thinks it owns the incoming argument stack, but that's not true for
"asmlinkage" functions, and it corrupts the caller-set-up argument stack
when it pushes the third argument onto the stack.  Which can result in
%ebx getting corrupted in user space.

Now, normally nobody sane would ever notice, since libc will save and
restore %ebx anyway over the system call, but it's still wrong.

I'd much rather have "asmlinkage" tell gcc directly that it doesn't own
the stack, but no such attribute exists, so we're stuck with our hacky
manual "prevent_tail_call()" macro once more (we've had the same issue
before with sys_waitpid() and sys_wait4()).

Thanks to Hans-Werner Hilse <hilse@sub.uni-goettingen.de> for reporting
the issue and testing the fix.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Linus Torvalds committed Apr 18, 2006
1 parent ac69e97 commit 0a489cb
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)

asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
{
return do_sys_ftruncate(fd, length, 1);
long ret = do_sys_ftruncate(fd, length, 1);
prevent_tail_call(ret);
return ret;
}

/* LFS versions of truncate are only needed on 32 bit machines */
Expand All @@ -343,7 +345,9 @@ asmlinkage long sys_truncate64(const char __user * path, loff_t length)

asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
{
return do_sys_ftruncate(fd, length, 0);
long ret = do_sys_ftruncate(fd, length, 0);
prevent_tail_call(ret);
return ret;
}
#endif

Expand Down

0 comments on commit 0a489cb

Please sign in to comment.