Re: execve(NULL, argv, envp) for nommu?

Oleg Nesterov <[email protected]>
Newsgroups org.kernel.vger.linux-embedded,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 09/12, Oleg Nesterov wrote:
>
> On 09/12, Rob Landley wrote:
> >
> > On 09/11/2017 10:15 AM, Oleg Nesterov wrote:
> > > On 09/08, Rob Landley wrote:
> > >>
> > >> So is exec(NULL, argv, envp) a reasonable thing to want?
> > >
> > > I think that something like prctl(PR_OPEN_EXE_FILE) which does
> > >
> > > 	dentry_open(current->mm->exe_file->path, O_PATH)
> > >
> > > and returns fd make more sense.
> > >
> > > Then you can do execveat(fd, "", ..., AT_EMPTY_PATH).
> > I'm all for it? That sounds like a cosmetic difference, a more verbose
> > way of achieving the same outcome.
>
> Simpler to implement. Something like the (untested) patch below. Not sure
> it is correct, not sure it is good idea, etc.

OTOH... with the trivial patch below

	execveat(AT_FDCWD, "", NULL, NULL, AT_EMPTY_PATH);

should always work, even if the binary is not in scope after chroot, or if
it is no longer executable, or unlinked. But I am not sure what else should
we do to avoid the security problems.

Oleg.


--- x/fs/exec.c
+++ x/fs/exec.c
@@ -832,23 +832,32 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
 {
 	struct file *file;
 	int err;
-	struct open_flags open_exec_flags = {
-		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
-		.acc_mode = MAY_EXEC,
-		.intent = LOOKUP_OPEN,
-		.lookup_flags = LOOKUP_FOLLOW,
-	};
-
-	if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
-		return ERR_PTR(-EINVAL);
-	if (flags & AT_SYMLINK_NOFOLLOW)
-		open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW;
-	if (flags & AT_EMPTY_PATH)
-		open_exec_flags.lookup_flags |= LOOKUP_EMPTY;
 
-	file = do_filp_open(fd, name, &open_exec_flags);
-	if (IS_ERR(file))
-		goto out;
+	if (fd == AT_FDCWD && name->name[0] == '\0' && flags == AT_EMPTY_PATH) {
+		file = get_mm_exe_file(current->mm);
+		if (!file) {
+			file = ERR_PTR(-ENOENT);
+			goto out;
+		}
+	} else {
+		struct open_flags open_exec_flags = {
+			.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
+			.acc_mode = MAY_EXEC,
+			.intent = LOOKUP_OPEN,
+			.lookup_flags = LOOKUP_FOLLOW,
+		};
+
+		if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
+			return ERR_PTR(-EINVAL);
+		if (flags & AT_SYMLINK_NOFOLLOW)
+			open_exec_flags.lookup_flags &= ~LOOKUP_FOLLOW;
+		if (flags & AT_EMPTY_PATH)
+			open_exec_flags.lookup_flags |= LOOKUP_EMPTY;
+
+		file = do_filp_open(fd, name, &open_exec_flags);
+		if (IS_ERR(file))
+			goto out;
+	}
 
 	err = -EACCES;
 	if (!S_ISREG(file_inode(file)->i_mode))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.