Revert "Revert "exec: move S_ISREG() check earlier""

This reverts commit 29298d156e as Kees has
submitted something upstream to fix this properly.

Cc: Kees Cook <keescook@google.com>
Cc: Marc Zyngier <mzyngier@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Id3220d4220e77ee6cbabc4a0ccae06acef726f0e
This commit is contained in:
Greg Kroah-Hartman
2020-08-14 09:11:29 +02:00
parent 38f5fe502c
commit af494fd94b
3 changed files with 18 additions and 10 deletions
+14 -2
View File
@@ -141,8 +141,14 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
if (IS_ERR(file))
goto out;
/*
* may_open() has already checked for this, so it should be
* impossible to trip now. But we need to be extra cautious
* and check again at the very end too.
*/
error = -EACCES;
if ((!S_ISREG(file_inode(file)->i_mode) || path_noexec(&file->f_path)))
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
path_noexec(&file->f_path)))
goto exit;
fsnotify_open(file);
@@ -905,8 +911,14 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
if (IS_ERR(file))
goto out;
/*
* may_open() has already checked for this, so it should be
* impossible to trip now. But we need to be extra cautious
* and check again at the very end too.
*/
err = -EACCES;
if ((!S_ISREG(file_inode(file)->i_mode) || path_noexec(&file->f_path)))
if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) ||
path_noexec(&file->f_path)))
goto exit;
err = deny_write_access(file);
+4 -2
View File
@@ -2933,16 +2933,18 @@ static int may_open(const struct path *path, int acc_mode, int flag)
case S_IFLNK:
return -ELOOP;
case S_IFDIR:
if (acc_mode & MAY_WRITE)
if (acc_mode & (MAY_WRITE | MAY_EXEC))
return -EISDIR;
break;
case S_IFBLK:
case S_IFCHR:
if (!may_open_dev(path))
return -EACCES;
/*FALLTHRU*/
fallthrough;
case S_IFIFO:
case S_IFSOCK:
if (acc_mode & MAY_EXEC)
return -EACCES;
flag &= ~O_TRUNC;
break;
case S_IFREG:
-6
View File
@@ -779,12 +779,6 @@ static int do_dentry_open(struct file *f,
return 0;
}
/* Any file opened for execve()/uselib() has to be a regular file. */
if (unlikely(f->f_flags & FMODE_EXEC && !S_ISREG(inode->i_mode))) {
error = -EACCES;
goto cleanup_file;
}
if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
error = get_write_access(inode);
if (unlikely(error))