* Re: [RFC] "Text file busy" when overwriting libraries
@ 2001-10-14 14:50 Samium Gromoff
0 siblings, 0 replies; 11+ messages in thread
From: Samium Gromoff @ 2001-10-14 14:50 UTC (permalink / raw)
To: linux-kernel
> This isnt a problem worth solving. Shared libraries are managed by the
> superuser. The shared library tools already do the right thing. The
> superuser can equally reboot the machine or reformat the disk by accident
> anyway.
Sounds _very_ true for me...
cheers, Samium Gromoff
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-15 12:08 ` Alan Cox
@ 2001-10-15 12:11 ` Alexander Viro
0 siblings, 0 replies; 11+ messages in thread
From: Alexander Viro @ 2001-10-15 12:11 UTC (permalink / raw)
To: Alan Cox; +Cc: Eric W. Biederman, Linus Torvalds, linux-kernel
On Mon, 15 Oct 2001, Alan Cox wrote:
> > Anyone can write it, but what the hell will he do without write access to
> > any place that wouldn't be mounted noexec? Environment can be restricted
> > even if you give them shell...
>
> He will type "perl" and interactively issue any damn syscall he likes
> subject to the normal permissions rules. Noexec is only useful for a user
> given virtually nothing.
... and will hit "permission denied" on attempt to exec /usr/bin/perl.
Blanket noexec on /usr instance mounted in his chroot with selective turning
the thing off on some binaries. And yes, I realize that one can always
hunt for buffer overruns in sh(1)...
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-15 11:57 ` Alexander Viro
@ 2001-10-15 12:08 ` Alan Cox
2001-10-15 12:11 ` Alexander Viro
0 siblings, 1 reply; 11+ messages in thread
From: Alan Cox @ 2001-10-15 12:08 UTC (permalink / raw)
To: Alexander Viro; +Cc: Alan Cox, Eric W. Biederman, Linus Torvalds, linux-kernel
> Anyone can write it, but what the hell will he do without write access to
> any place that wouldn't be mounted noexec? Environment can be restricted
> even if you give them shell...
He will type "perl" and interactively issue any damn syscall he likes
subject to the normal permissions rules. Noexec is only useful for a user
given virtually nothing.
ALan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-15 11:54 ` Alan Cox
@ 2001-10-15 11:57 ` Alexander Viro
2001-10-15 12:08 ` Alan Cox
0 siblings, 1 reply; 11+ messages in thread
From: Alexander Viro @ 2001-10-15 11:57 UTC (permalink / raw)
To: Alan Cox; +Cc: Eric W. Biederman, Linus Torvalds, linux-kernel
On Mon, 15 Oct 2001, Alan Cox wrote:
> Which is mostly useless anyway since anyone can write an ld-linux that
> doesn't check providing the binary is readable. noexec is basically a weird
> ancient unixism that is usless.
Anyone can write it, but what the hell will he do without write access to
any place that wouldn't be mounted noexec? Environment can be restricted
even if you give them shell...
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-15 10:11 ` Eric W. Biederman
@ 2001-10-15 11:54 ` Alan Cox
2001-10-15 11:57 ` Alexander Viro
0 siblings, 1 reply; 11+ messages in thread
From: Alan Cox @ 2001-10-15 11:54 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Linus Torvalds, Alan Cox, Alexander Viro, linux-kernel
> Just to reiterate I see this as a solution to two problems
> 1) It adds an additional safety check that shared libraries won't
> mutate under you.
Which prevents a user with rights doing so deliberately.
> 2) It allows user space access to the security policy information
> regarding executables. Allowing ld-linux.so to refust to
> execute binaries, and shared libaries on a filesystem mounted
> noexec.
Which is mostly useless anyway since anyone can write an ld-linux that
doesn't check providing the binary is readable. noexec is basically a weird
ancient unixism that is usless.
> My biggest unresolved issue is which numbers to choose for O_EXEC on
> every platform. As the DENYWRITE code is cleaner in open than in mmap.
And the fact that open has side effects.
Alan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-15 2:06 ` Linus Torvalds
@ 2001-10-15 10:11 ` Eric W. Biederman
2001-10-15 11:54 ` Alan Cox
0 siblings, 1 reply; 11+ messages in thread
From: Eric W. Biederman @ 2001-10-15 10:11 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Alan Cox, Alexander Viro, linux-kernel
Linus Torvalds <torvalds@transmeta.com> writes:
> On Mon, 15 Oct 2001, Alan Cox wrote:
> >
> > > We already can open an exec only file just open("file", 0).
> >
> > Wrong.
Grr. All of that munging about with the permission bits confused me.
We do allow a no permission open in open_namei (which is what
I was staring at), we just can't generate it with filp_open. So my
open_exec needs to call open_namei directly oh well. I never intended
to allow a weird case like that, or imply that I would allow it.
Since I now have the permission checks seperate between user space,
and kernel space. I have added an additional check that O_EXEC
fails if anyone has write permission to the file. So the permissions
must be r-xr-xr-x on the file.
Just to reiterate I see this as a solution to two problems
1) It adds an additional safety check that shared libraries won't
mutate under you.
2) It allows user space access to the security policy information
regarding executables. Allowing ld-linux.so to refust to
execute binaries, and shared libaries on a filesystem mounted
noexec.
And even if this doesn't get exported to user space I see this as
a small code cleanup. That simplifies MAP_DENYWRITE implementation.
My biggest unresolved issue is which numbers to choose for O_EXEC on
every platform. As the DENYWRITE code is cleaner in open than in mmap.
Eric
diff -uNrX linux-ignore-files linux-2.4.12/Documentation/Changes linux-2.4.12.eb3/Documentation/Changes
--- linux-2.4.12/Documentation/Changes Sat Oct 13 16:19:40 2001
+++ linux-2.4.12.eb3/Documentation/Changes Sun Oct 14 01:39:38 2001
@@ -126,6 +126,13 @@
32-bit UID support is now in place. Have fun!
+A new flag O_EXEC has been added to the open call. While a file
+is opened O_EXEC you get ETXTBSY errors if you attempt to write it.
+This allows shared libraries to have the same garanutee against
+changes as normal executables do. The permissions requirements
+to open a file O_EXEC are (a) no one has it open read/write and
+(b) that the open has execute permissions on the file.
+
Linux documentation for functions is transitioning to inline
documentation via specially-formatted comments near their
definitions in the source. These comments can be combined with the
diff -uNrX linux-ignore-files linux-2.4.12/arch/alpha/kernel/osf_sys.c linux-2.4.12.eb3/arch/alpha/kernel/osf_sys.c
--- linux-2.4.12/arch/alpha/kernel/osf_sys.c Sat Oct 13 16:18:56 2001
+++ linux-2.4.12.eb3/arch/alpha/kernel/osf_sys.c Sat Oct 13 17:15:04 2001
@@ -240,7 +240,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flags, off);
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/arch/arm/kernel/sys_arm.c linux-2.4.12.eb3/arch/arm/kernel/sys_arm.c
--- linux-2.4.12/arch/arm/kernel/sys_arm.c Wed Jul 25 03:08:24 2001
+++ linux-2.4.12.eb3/arch/arm/kernel/sys_arm.c Sat Oct 13 17:07:57 2001
@@ -58,7 +58,7 @@
int error = -EINVAL;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
/*
* If we are doing a fixed mapping, and address < PAGE_SIZE,
diff -uNrX linux-ignore-files linux-2.4.12/arch/cris/kernel/sys_cris.c linux-2.4.12.eb3/arch/cris/kernel/sys_cris.c
--- linux-2.4.12/arch/cris/kernel/sys_cris.c Sat Aug 11 09:50:04 2001
+++ linux-2.4.12.eb3/arch/cris/kernel/sys_cris.c Sat Oct 13 17:14:06 2001
@@ -52,7 +52,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/i386/kernel/sys_i386.c linux-2.4.12.eb3/arch/i386/kernel/sys_i386.c
--- linux-2.4.12/arch/i386/kernel/sys_i386.c Sat Apr 14 13:36:44 2001
+++ linux-2.4.12.eb3/arch/i386/kernel/sys_i386.c Sat Oct 13 17:08:07 2001
@@ -48,7 +48,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/ia64/ia32/sys_ia32.c linux-2.4.12.eb3/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.12/arch/ia64/ia32/sys_ia32.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb3/arch/ia64/ia32/sys_ia32.c Sat Oct 13 17:15:34 2001
@@ -282,7 +282,7 @@
long error = -EFAULT;
unsigned int poff;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
prot |= PROT_EXEC;
if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
diff -uNrX linux-ignore-files linux-2.4.12/arch/ia64/kernel/sys_ia64.c linux-2.4.12.eb3/arch/ia64/kernel/sys_ia64.c
--- linux-2.4.12/arch/ia64/kernel/sys_ia64.c Sat Aug 11 09:50:05 2001
+++ linux-2.4.12.eb3/arch/ia64/kernel/sys_ia64.c Sat Oct 13 17:10:39 2001
@@ -178,7 +178,7 @@
unsigned long roff;
struct file *file = 0;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/m68k/kernel/sys_m68k.c linux-2.4.12.eb3/arch/m68k/kernel/sys_m68k.c
--- linux-2.4.12/arch/m68k/kernel/sys_m68k.c Wed Jul 25 03:07:49 2001
+++ linux-2.4.12.eb3/arch/m68k/kernel/sys_m68k.c Sat Oct 13 17:11:13 2001
@@ -52,7 +52,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
@@ -104,7 +104,7 @@
if (a.offset & ~PAGE_MASK)
goto out;
- a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ a.flags &= ~(MAP_EXECUTABLE);
error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
out:
@@ -144,7 +144,7 @@
if (!file)
goto out;
}
- a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ a.flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips/kernel/irixelf.c linux-2.4.12.eb3/arch/mips/kernel/irixelf.c
--- linux-2.4.12/arch/mips/kernel/irixelf.c Sat Apr 14 13:36:44 2001
+++ linux-2.4.12.eb3/arch/mips/kernel/irixelf.c Sun Oct 14 00:35:14 2001
@@ -298,7 +298,7 @@
eppnt = elf_phdata;
for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
if(eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+ int elf_type = MAP_PRIVATE;
int elf_prot = 0;
unsigned long vaddr = 0;
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
@@ -479,7 +479,7 @@
return 0;
}
-#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE)
+#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE)
static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum,
unsigned int *estack, unsigned int *laddr,
@@ -776,7 +776,6 @@
return retval;
out_free_dentry:
- allow_write_access(interpreter);
fput(interpreter);
out_free_interp:
if (elf_interpreter)
@@ -842,7 +841,7 @@
elf_phdata->p_vaddr & 0xfffff000,
elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
elf_phdata->p_offset & 0xfffff000);
up_write(¤t->mm->mmap_sem);
@@ -919,7 +918,7 @@
down_write(¤t->mm->mmap_sem);
retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000),
(hp->p_filesz + (hp->p_vaddr & 0xfff)),
- prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
+ prot, (MAP_FIXED | MAP_PRIVATE),
(hp->p_offset & 0xfffff000));
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips/kernel/syscall.c linux-2.4.12.eb3/arch/mips/kernel/syscall.c
--- linux-2.4.12/arch/mips/kernel/syscall.c Wed Jul 25 03:07:50 2001
+++ linux-2.4.12.eb3/arch/mips/kernel/syscall.c Sat Oct 13 17:11:32 2001
@@ -62,7 +62,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips/kernel/sysirix.c linux-2.4.12.eb3/arch/mips/kernel/sysirix.c
--- linux-2.4.12/arch/mips/kernel/sysirix.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb3/arch/mips/kernel/sysirix.c Sat Oct 13 17:16:16 2001
@@ -1080,7 +1080,7 @@
}
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, offset);
@@ -1640,7 +1640,7 @@
}
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips64/kernel/syscall.c linux-2.4.12.eb3/arch/mips64/kernel/syscall.c
--- linux-2.4.12/arch/mips64/kernel/syscall.c Sat Oct 13 16:19:43 2001
+++ linux-2.4.12.eb3/arch/mips64/kernel/syscall.c Sat Oct 13 17:11:45 2001
@@ -63,7 +63,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
error = do_mmap(file, addr, len, prot, flags, offset);
diff -uNrX linux-ignore-files linux-2.4.12/arch/parisc/kernel/sys_parisc.c linux-2.4.12.eb3/arch/parisc/kernel/sys_parisc.c
--- linux-2.4.12/arch/parisc/kernel/sys_parisc.c Sat Apr 14 13:36:45 2001
+++ linux-2.4.12.eb3/arch/parisc/kernel/sys_parisc.c Sat Oct 13 17:13:55 2001
@@ -59,7 +59,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
error = do_mmap(file, addr, len, prot, flags, offset);
if (file != NULL)
fput(file);
diff -uNrX linux-ignore-files linux-2.4.12/arch/ppc/kernel/syscalls.c linux-2.4.12.eb3/arch/ppc/kernel/syscalls.c
--- linux-2.4.12/arch/ppc/kernel/syscalls.c Wed Jul 25 03:07:25 2001
+++ linux-2.4.12.eb3/arch/ppc/kernel/syscalls.c Sat Oct 13 17:12:01 2001
@@ -196,7 +196,7 @@
struct file * file = NULL;
int ret = -EBADF;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
if (!(file = fget(fd)))
goto out;
diff -uNrX linux-ignore-files linux-2.4.12/arch/s390/kernel/sys_s390.c linux-2.4.12.eb3/arch/s390/kernel/sys_s390.c
--- linux-2.4.12/arch/s390/kernel/sys_s390.c Sat Apr 14 13:36:45 2001
+++ linux-2.4.12.eb3/arch/s390/kernel/sys_s390.c Sat Oct 13 17:13:33 2001
@@ -54,7 +54,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/s390x/kernel/linux32.c linux-2.4.12.eb3/arch/s390x/kernel/linux32.c
--- linux-2.4.12/arch/s390x/kernel/linux32.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb3/arch/s390x/kernel/linux32.c Sat Oct 13 20:13:59 2001
@@ -2923,12 +2923,10 @@
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count32(argv)) < 0) {
- allow_write_access(file);
fput(file);
return bprm.argc;
}
if ((bprm.envc = count32(envp)) < 0) {
- allow_write_access(file);
fput(file);
return bprm.envc;
}
@@ -2957,7 +2955,6 @@
out:
/* Something went wrong, return the inode and free the argument pages*/
- allow_write_access(bprm.file);
if (bprm.file)
fput(bprm.file);
@@ -4179,7 +4176,7 @@
struct file * file = NULL;
unsigned long error = -EBADF;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/s390x/kernel/sys_s390.c linux-2.4.12.eb3/arch/s390x/kernel/sys_s390.c
--- linux-2.4.12/arch/s390x/kernel/sys_s390.c Thu May 3 01:46:43 2001
+++ linux-2.4.12.eb3/arch/s390x/kernel/sys_s390.c Sat Oct 13 17:14:23 2001
@@ -54,7 +54,7 @@
long error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/sh/kernel/sys_sh.c linux-2.4.12.eb3/arch/sh/kernel/sys_sh.c
--- linux-2.4.12/arch/sh/kernel/sys_sh.c Sat Oct 13 16:19:45 2001
+++ linux-2.4.12.eb3/arch/sh/kernel/sys_sh.c Sat Oct 13 17:12:17 2001
@@ -89,7 +89,7 @@
int error = -EBADF;
struct file *file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc/kernel/sys_sparc.c linux-2.4.12.eb3/arch/sparc/kernel/sys_sparc.c
--- linux-2.4.12/arch/sparc/kernel/sys_sparc.c Thu May 3 01:46:43 2001
+++ linux-2.4.12.eb3/arch/sparc/kernel/sys_sparc.c Sat Oct 13 17:12:40 2001
@@ -240,7 +240,7 @@
if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
goto out_putf;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc/kernel/sys_sunos.c linux-2.4.12.eb3/arch/sparc/kernel/sys_sunos.c
--- linux-2.4.12/arch/sparc/kernel/sys_sunos.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb3/arch/sparc/kernel/sys_sunos.c Sun Oct 14 00:35:47 2001
@@ -115,7 +115,7 @@
goto out_putf;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, off);
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/binfmt_aout32.c linux-2.4.12.eb3/arch/sparc64/kernel/binfmt_aout32.c
--- linux-2.4.12/arch/sparc64/kernel/binfmt_aout32.c Wed Jul 25 03:08:26 2001
+++ linux-2.4.12.eb3/arch/sparc64/kernel/binfmt_aout32.c Sun Oct 14 00:36:22 2001
@@ -280,7 +280,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset);
up_write(¤t->mm->mmap_sem);
@@ -292,7 +292,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
up_write(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
@@ -372,7 +372,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
N_TXTOFF(ex));
up_write(¤t->mm->mmap_sem);
retval = error;
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/sys_sparc.c linux-2.4.12.eb3/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.12/arch/sparc64/kernel/sys_sparc.c Thu May 3 01:46:44 2001
+++ linux-2.4.12.eb3/arch/sparc64/kernel/sys_sparc.c Sat Oct 13 17:13:19 2001
@@ -277,7 +277,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
len = PAGE_ALIGN(len);
retval = -EINVAL;
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/sys_sparc32.c linux-2.4.12.eb3/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.12/arch/sparc64/kernel/sys_sparc32.c Sat Oct 13 16:21:40 2001
+++ linux-2.4.12.eb3/arch/sparc64/kernel/sys_sparc32.c Sat Oct 13 20:28:49 2001
@@ -2998,12 +2998,10 @@
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.argc;
}
if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.envc;
}
@@ -3032,7 +3030,6 @@
out:
/* Something went wrong, return the inode and free the argument pages*/
- allow_write_access(bprm.file);
if (bprm.file)
fput(bprm.file);
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/sys_sunos32.c linux-2.4.12.eb3/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.12/arch/sparc64/kernel/sys_sunos32.c Sat Oct 13 16:18:58 2001
+++ linux-2.4.12.eb3/arch/sparc64/kernel/sys_sunos32.c Sat Oct 13 17:16:57 2001
@@ -99,7 +99,7 @@
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/solaris/misc.c linux-2.4.12.eb3/arch/sparc64/solaris/misc.c
--- linux-2.4.12/arch/sparc64/solaris/misc.c Sat Oct 13 16:19:45 2001
+++ linux-2.4.12.eb3/arch/sparc64/solaris/misc.c Sat Oct 13 17:17:17 2001
@@ -93,7 +93,7 @@
flags &= ~_MAP_NEW;
down_write(¤t->mm->mmap_sem);
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
(unsigned long) prot, (unsigned long) flags, off);
Binary files linux-2.4.12/drivers/net/hamradio/soundmodem/gentbl and linux-2.4.12.eb3/drivers/net/hamradio/soundmodem/gentbl differ
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_aout.c linux-2.4.12.eb3/fs/binfmt_aout.c
--- linux-2.4.12/fs/binfmt_aout.c Sat Oct 13 16:21:50 2001
+++ linux-2.4.12.eb3/fs/binfmt_aout.c Sun Oct 14 00:59:39 2001
@@ -380,7 +380,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset);
up_write(¤t->mm->mmap_sem);
@@ -392,7 +392,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
up_write(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
@@ -479,7 +479,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
N_TXTOFF(ex));
up_write(¤t->mm->mmap_sem);
retval = error;
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_elf.c linux-2.4.12.eb3/fs/binfmt_elf.c
--- linux-2.4.12/fs/binfmt_elf.c Sat Oct 13 16:21:50 2001
+++ linux-2.4.12.eb3/fs/binfmt_elf.c Sun Oct 14 00:38:37 2001
@@ -288,7 +288,7 @@
eppnt = elf_phdata;
for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+ int elf_type = MAP_PRIVATE;
int elf_prot = 0;
unsigned long vaddr = 0;
unsigned long k, map_addr;
@@ -642,7 +642,7 @@
if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
- elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
+ elf_flags = MAP_PRIVATE|MAP_EXECUTABLE;
vaddr = elf_ppnt->p_vaddr;
if (elf_ex.e_type == ET_EXEC || load_addr_set) {
@@ -701,7 +701,6 @@
interpreter,
&interp_load_addr);
- allow_write_access(interpreter);
fput(interpreter);
kfree(elf_interpreter);
@@ -789,7 +788,6 @@
/* error cleanup */
out_free_dentry:
- allow_write_access(interpreter);
fput(interpreter);
out_free_interp:
if (elf_interpreter)
@@ -853,7 +851,7 @@
(elf_phdata->p_filesz +
ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
(elf_phdata->p_offset -
ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_em86.c linux-2.4.12.eb3/fs/binfmt_em86.c
--- linux-2.4.12/fs/binfmt_em86.c Sat Mar 17 16:28:29 2001
+++ linux-2.4.12.eb3/fs/binfmt_em86.c Sat Oct 13 20:12:38 2001
@@ -44,7 +44,6 @@
}
bprm->sh_bang++; /* Well, the bang-shell is implicit... */
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_misc.c linux-2.4.12.eb3/fs/binfmt_misc.c
--- linux-2.4.12/fs/binfmt_misc.c Sat Mar 17 16:28:29 2001
+++ linux-2.4.12.eb3/fs/binfmt_misc.c Sat Oct 13 20:12:46 2001
@@ -201,7 +201,6 @@
if (!fmt)
goto _ret;
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_script.c linux-2.4.12.eb3/fs/binfmt_script.c
--- linux-2.4.12/fs/binfmt_script.c Sat Mar 17 16:28:29 2001
+++ linux-2.4.12.eb3/fs/binfmt_script.c Sat Oct 13 20:12:30 2001
@@ -29,7 +29,6 @@
*/
bprm->sh_bang++;
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/exec.c linux-2.4.12.eb3/fs/exec.c
--- linux-2.4.12/fs/exec.c Sat Oct 13 16:20:02 2001
+++ linux-2.4.12.eb3/fs/exec.c Mon Oct 15 03:46:21 2001
@@ -337,39 +337,17 @@
struct file *open_exec(const char *name)
{
+ int error;
struct nameidata nd;
- struct inode *inode;
- struct file *file;
- int err = 0;
- if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
- err = path_walk(name, &nd);
- file = ERR_PTR(err);
- if (!err) {
- inode = nd.dentry->d_inode;
- file = ERR_PTR(-EACCES);
- if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
- S_ISREG(inode->i_mode)) {
- int err = permission(inode, MAY_EXEC);
- if (!err && !(inode->i_mode & 0111))
- err = -EACCES;
- file = ERR_PTR(err);
- if (!err) {
- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
- fput(file);
- file = ERR_PTR(err);
- }
- }
-out:
- return file;
- }
- }
- path_release(&nd);
- }
- goto out;
+ /* For a real exec we cheat. We don't do permission checks
+ * for read, but we open the file for reading anyway...
+ */
+ error = open_namei(name, O_EXEC, 0, &nd);
+ if (!error)
+ return dentry_open(nd.dentry, nd.mnt, O_EXEC | O_RDONLY);
+
+ return ERR_PTR(error);
}
int kernel_read(struct file *file, unsigned long offset,
@@ -774,7 +752,6 @@
struct file * file;
unsigned long loader;
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
@@ -809,7 +786,6 @@
retval = fn(bprm, regs);
if (retval >= 0) {
put_binfmt(fmt);
- allow_write_access(bprm->file);
if (bprm->file)
fput(bprm->file);
bprm->file = NULL;
@@ -871,13 +847,11 @@
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.argc;
}
if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.envc;
}
@@ -906,7 +880,6 @@
out:
/* Something went wrong, return the inode and free the argument pages*/
- allow_write_access(bprm.file);
if (bprm.file)
fput(bprm.file);
diff -uNrX linux-ignore-files linux-2.4.12/fs/file_table.c linux-2.4.12.eb3/fs/file_table.c
--- linux-2.4.12/fs/file_table.c Sat Oct 13 16:20:02 2001
+++ linux-2.4.12.eb3/fs/file_table.c Sat Oct 13 20:00:23 2001
@@ -114,6 +114,8 @@
fops_put(file->f_op);
if (file->f_mode & FMODE_WRITE)
put_write_access(inode);
+ if (file->f_mode & FMODE_EXEC)
+ allow_write_access(inode);
file_list_lock();
file->f_dentry = NULL;
file->f_vfsmnt = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/namei.c linux-2.4.12.eb3/fs/namei.c
--- linux-2.4.12/fs/namei.c Sat Oct 13 16:22:01 2001
+++ linux-2.4.12.eb3/fs/namei.c Mon Oct 15 03:52:33 2001
@@ -212,10 +212,10 @@
* put_write_access() releases this write permission.
* This is used for regular files.
* We cannot support write (and maybe mmap read-write shared) accesses and
- * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
- * can have the following values:
- * 0: no writers, no VM_DENYWRITE mappings
- * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
+ * O_EXEC mmappings simultaneously. The i_writecount field of an inode can have
+ * the following values:
+ * 0: no writers, no executers.
+ * < 0: (-i_writecount) users are executing the file.
* > 0: (i_writecount) users are writing to the file.
*
* Normally we operate on that counter with atomic_{inc,dec} and it's safe
@@ -974,6 +974,8 @@
int count = 0;
acc_mode = ACC_MODE(flag);
+ if (flag & O_EXEC)
+ acc_mode |= MAY_EXEC;
/*
* The simplest case - just a plain lookup.
@@ -1069,6 +1071,22 @@
error = -EISDIR;
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
goto exit;
+
+ error = -EACCES;
+ if (flag & O_EXEC) {
+ if (flag & FMODE_WRITE)
+ goto exit;
+ if (nd->mnt->mnt_flags & MNT_NOEXEC)
+ goto exit;
+ if (!S_ISREG(inode->i_mode))
+ goto exit;
+ /* The follow check for an executable bit was taken
+ * from the old open_exec. I don't think it is either
+ * needed or makes any sense but just in case...
+ */
+ if (!(inode->i_mode & S_IXUGO))
+ goto exit;
+ }
error = permission(inode,acc_mode);
if (error)
diff -uNrX linux-ignore-files linux-2.4.12/fs/open.c linux-2.4.12.eb3/fs/open.c
--- linux-2.4.12/fs/open.c Sat Oct 13 16:21:50 2001
+++ linux-2.4.12.eb3/fs/open.c Mon Oct 15 03:45:49 2001
@@ -612,6 +612,8 @@
* 11 - read-write
* for the internal routines (ie open_namei()/follow_link() etc). 00 is
* used by symlinks.
+ *
+ * The mapping is: 00 -> 01 , 01 -> 10, 10 -> 11, 11 -> 11
*/
struct file *filp_open(const char * filename, int flags, int mode)
{
@@ -625,6 +627,11 @@
namei_flags |= 2;
error = open_namei(filename, namei_flags, mode, &nd);
+ /* For now don't allow O_EXEC from userspace when anyone can
+ * write to the file.
+ */
+ if (!error && (flags & O_EXEC) && (nd.dentry->d_inode->i_mode & S_IWUGO))
+ error = -EACCES;
if (!error)
return dentry_open(nd.dentry, nd.mnt, flags);
@@ -644,6 +651,8 @@
goto cleanup_dentry;
f->f_flags = flags;
f->f_mode = (flags+1) & O_ACCMODE;
+ if (flags & O_EXEC)
+ f->f_mode |= FMODE_EXEC;
inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
@@ -673,6 +682,12 @@
goto cleanup_all;
}
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+
+ if (f->f_mode & FMODE_EXEC) {
+ error = deny_write_access(f);
+ if (error)
+ goto cleanup_all;
+ }
return f;
diff -uNrX linux-ignore-files linux-2.4.12/include/asm-i386/fcntl.h linux-2.4.12.eb3/include/asm-i386/fcntl.h
--- linux-2.4.12/include/asm-i386/fcntl.h Sat Oct 13 16:20:04 2001
+++ linux-2.4.12.eb3/include/asm-i386/fcntl.h Sun Oct 14 00:08:01 2001
@@ -7,6 +7,7 @@
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
+#define O_EXEC 04 /* generate ETXTBSY on writes */
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
diff -uNrX linux-ignore-files linux-2.4.12/include/linux/fs.h linux-2.4.12.eb3/include/linux/fs.h
--- linux-2.4.12/include/linux/fs.h Sat Oct 13 17:26:25 2001
+++ linux-2.4.12.eb3/include/linux/fs.h Sun Oct 14 00:42:30 2001
@@ -73,6 +73,7 @@
#define FMODE_READ 1
#define FMODE_WRITE 2
+#define FMODE_EXEC 4
#define READ 0
#define WRITE 1
diff -uNrX linux-ignore-files linux-2.4.12/kernel/fork.c linux-2.4.12.eb3/kernel/fork.c
--- linux-2.4.12/kernel/fork.c Sat Oct 13 16:20:09 2001
+++ linux-2.4.12.eb3/kernel/fork.c Sat Oct 13 20:34:56 2001
@@ -168,8 +168,6 @@
if (file) {
struct inode *inode = file->f_dentry->d_inode;
get_file(file);
- if (tmp->vm_flags & VM_DENYWRITE)
- atomic_dec(&inode->i_writecount);
/* insert tmp into the share list, just after mpnt */
spin_lock(&inode->i_mapping->i_shared_lock);
diff -uNrX linux-ignore-files linux-2.4.12/mm/mmap.c linux-2.4.12.eb3/mm/mmap.c
--- linux-2.4.12/mm/mmap.c Sat Oct 13 16:21:52 2001
+++ linux-2.4.12.eb3/mm/mmap.c Sun Oct 14 00:50:32 2001
@@ -98,9 +98,6 @@
struct file * file = vma->vm_file;
if (file) {
- struct inode *inode = file->f_dentry->d_inode;
- if (vma->vm_flags & VM_DENYWRITE)
- atomic_inc(&inode->i_writecount);
if(vma->vm_next_share)
vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
*vma->vm_pprev_share = vma->vm_next_share;
@@ -205,7 +202,6 @@
_trans(prot, PROT_EXEC, VM_EXEC);
flag_bits =
_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) |
- _trans(flags, MAP_DENYWRITE, VM_DENYWRITE) |
_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE);
return prot_bits | flag_bits;
#undef _trans
@@ -310,9 +306,6 @@
struct address_space *mapping = inode->i_mapping;
struct vm_area_struct **head;
- if (vma->vm_flags & VM_DENYWRITE)
- atomic_dec(&inode->i_writecount);
-
head = &mapping->i_mmap;
if (vma->vm_flags & VM_SHARED)
head = &mapping->i_mmap_shared;
@@ -395,7 +388,6 @@
struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev;
unsigned int vm_flags;
- int correct_wcount = 0;
int error;
rb_node_t ** rb_link, * rb_parent;
@@ -526,12 +518,6 @@
error = -EINVAL;
if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
goto free_vma;
- if (vm_flags & VM_DENYWRITE) {
- error = deny_write_access(file);
- if (error)
- goto free_vma;
- correct_wcount = 1;
- }
vma->vm_file = file;
get_file(file);
error = file->f_op->mmap(file, vma);
@@ -551,8 +537,6 @@
addr = vma->vm_start;
vma_link(mm, vma, prev, rb_link, rb_parent);
- if (correct_wcount)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
out:
mm->total_vm += len >> PAGE_SHIFT;
@@ -563,8 +547,6 @@
return addr;
unmap_and_free_vma:
- if (correct_wcount)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
vma->vm_file = NULL;
fput(file);
@@ -946,11 +928,9 @@
* so release them, and unmap the page range..
* If the one of the segments is only being partially unmapped,
* it will put new vm_area_struct(s) into the address space.
- * In that case we have to be careful with VM_DENYWRITE.
*/
while ((mpnt = free) != NULL) {
unsigned long st, end, size;
- struct file *file = NULL;
free = free->vm_next;
@@ -959,11 +939,6 @@
end = end > mpnt->vm_end ? mpnt->vm_end : end;
size = end - st;
- if (mpnt->vm_flags & VM_DENYWRITE &&
- (st != mpnt->vm_start || end != mpnt->vm_end) &&
- (file = mpnt->vm_file) != NULL) {
- atomic_dec(&file->f_dentry->d_inode->i_writecount);
- }
remove_shared_vm_struct(mpnt);
mm->map_count--;
@@ -973,8 +948,6 @@
* Fix the mapping, and free the old area if it wasn't reused.
*/
extra = unmap_fixup(mm, mpnt, st, size, extra);
- if (file)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
}
validate_mm(mm);
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-15 1:44 ` Alan Cox
@ 2001-10-15 2:06 ` Linus Torvalds
2001-10-15 10:11 ` Eric W. Biederman
0 siblings, 1 reply; 11+ messages in thread
From: Linus Torvalds @ 2001-10-15 2:06 UTC (permalink / raw)
To: Alan Cox; +Cc: Eric W. Biederman, Alexander Viro, linux-kernel
On Mon, 15 Oct 2001, Alan Cox wrote:
>
> > We already can open an exec only file just open("file", 0).
>
> Wrong.
For exact details: there's a magic value, but it's 3.
open("file", 3)
will open the filename with neither read nor write permissions, but it
will actually _require_ both read- and write- permissions, and it was
historically a way to open a device just for ioctl's.
I don't think anybody actually uses it any more.
Linus
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-14 20:48 ` Eric W. Biederman
@ 2001-10-15 1:44 ` Alan Cox
2001-10-15 2:06 ` Linus Torvalds
0 siblings, 1 reply; 11+ messages in thread
From: Alan Cox @ 2001-10-15 1:44 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Alan Cox, Linus Torvalds, Alexander Viro, linux-kernel
> We already can open an exec only file just open("file", 0).
Wrong.
> In fact it looks like you can open a file with no permissions at all.
> You just can't do anything with it.
This isnt true. Read the code.
Alan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-14 12:08 ` Alan Cox
@ 2001-10-14 20:48 ` Eric W. Biederman
2001-10-15 1:44 ` Alan Cox
0 siblings, 1 reply; 11+ messages in thread
From: Eric W. Biederman @ 2001-10-14 20:48 UTC (permalink / raw)
To: Alan Cox; +Cc: Linus Torvalds, Alexander Viro, linux-kernel
Alan Cox <alan@lxorguk.ukuu.org.uk> writes:
> > My big question is how to correctly define O_EXEC for every
> > architecture. But I would like to know if there are objectionable
> > parts as well.
>
> It looks totally unworkable. Open() has side effects on a large number of
> platforms, and being able to open an exec only file might trigger them
> as well as all sorts of other potential problems where files are
> marked rwx by accident as is very common.
We already can open an exec only file just open("file", 0).
In fact it looks like you can open a file with no permissions at all.
You just can't do anything with it.
All O_EXEC does is stipulate that you must have the exec permission
to the file, and it does cause a side effect. Possibly it should
be broken into open, and then side effect. fcntl(fd,F_DENYWRITE).
My primary observation is that we don't need to manage the DENYWRITE
at the mmap level. The file descriptor level gets the job done with
less code, fewer suprises, fewer races.
> You narrow the DoS vulnerability and add a whole new set of open based
> ones.
You may be write. With the cleanup of the implementation by moving
everything into open (where we implement this for exec), it hadn't
occured to me that I might be opening a different kettle of fish.
> This isnt a problem worth solving. Shared libraries are managed by the
> superuser. The shared library tools already do the right thing. The
> superuser can equally reboot the machine or reformat the disk by accident
> anyway.
Yes the superuser can shoot himself in the foot, and by that argument
I should delete the entire implementation of MAP_DENYWRITE from the
kernel.
It is by no means true that the existing user space tools get it
right. I have multiple shared libraries where the owner has write
permission to them. And I do believe gcc -o foo.so does not do a
unlink/open(O_CREAT) pair. Nor does cp.
As for the superuser being the only one who touches shared libaries.
That is as true as it is that the superuser is the only one who
touches binaries, or scripts.
It is also quite unobvious that you shouldn't write to shared
libraries. If you have looked at how shared libaries are mapped and
you know that they are mapped into memory with mmap(MAP_PRIVATE), and
you understand how mmap works. It is quite obvious why you shouldn't
touch them. There are a lot of users that haven't done that however.
Accidental rwx permissions settings may indeed be a valid argument,
though I think that is more a bug in chmod, than anything else.
Eric
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] "Text file busy" when overwriting libraries
2001-10-14 8:02 ` [RFC] "Text file busy" when overwriting libraries Eric W. Biederman
@ 2001-10-14 12:08 ` Alan Cox
2001-10-14 20:48 ` Eric W. Biederman
0 siblings, 1 reply; 11+ messages in thread
From: Alan Cox @ 2001-10-14 12:08 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Linus Torvalds, Alan Cox, Alexander Viro, linux-kernel
> My big question is how to correctly define O_EXEC for every
> architecture. But I would like to know if there are objectionable
> parts as well.
It looks totally unworkable. Open() has side effects on a large number of
platforms, and being able to open an exec only file might trigger them
as well as all sorts of other potential problems where files are
marked rwx by accident as is very common.
You narrow the DoS vulnerability and add a whole new set of open based
ones.
This isnt a problem worth solving. Shared libraries are managed by the
superuser. The shared library tools already do the right thing. The
superuser can equally reboot the machine or reformat the disk by accident
anyway.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC] "Text file busy" when overwriting libraries
2001-10-05 16:58 Security question: "Text file busy" overwriting executables but Linus Torvalds
@ 2001-10-14 8:02 ` Eric W. Biederman
2001-10-14 12:08 ` Alan Cox
0 siblings, 1 reply; 11+ messages in thread
From: Eric W. Biederman @ 2001-10-14 8:02 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Alan Cox, Alexander Viro, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1509 bytes --]
Linus Torvalds <torvalds@transmeta.com> writes:
> I think it literally was /var/run/[uw]tmp, and using MAP_DENYWRITE to
> disable all logins.
>
> But it pretty much covers _any_ logfiles that are readable (and thus
> openable) by users.
Thank you for the help understanding the historical pitfalls.
> > Currently checking to see if the file is executable looks good
> > enough.
>
> [ executable by the user in question, not just anybody ]
>
> Yes, I suspect it is.
If it isn't we can add an extra check to make certain no one has
write permission to the file. But that feels icky.
Looking at the problem a little more you can do better than MAP_DENYWRITE.
Instead of dening write access per mapping we can more easily deny
write access from the open of a file. And add an O_EXEC option to open.
Adding the O_EXEC is possible now because we keep a struct file in the
vm_area_struct. Which was not the case when MAP_DENYWRITE was
written. This allows the mapping code to totally ignore the read only
mapping case.
What follows is my initial patch to implement O_EXEC against 2.4.12.
With this patch I totally delete MAP_DENYWRITE except in the arch
headers so we don't accidently reuse it's value. open_exec becomes
open_filp(O_EXEC | O_RDONLY). And now we don't have to manually
call allow_write_access whenever we call fput on a mapping.
My big question is how to correctly define O_EXEC for every
architecture. But I would like to know if there are objectionable
parts as well.
Eric
[-- Attachment #2: linux-2.4.12.eb2.diff --]
[-- Type: text/plain, Size: 29044 bytes --]
diff -uNrX linux-ignore-files linux-2.4.12/Documentation/Changes linux-2.4.12.eb2/Documentation/Changes
--- linux-2.4.12/Documentation/Changes Sat Oct 13 16:19:40 2001
+++ linux-2.4.12.eb2/Documentation/Changes Sun Oct 14 01:39:38 2001
@@ -126,6 +126,13 @@
32-bit UID support is now in place. Have fun!
+A new flag O_EXEC has been added to the open call. While a file
+is opened O_EXEC you get ETXTBSY errors if you attempt to write it.
+This allows shared libraries to have the same garanutee against
+changes as normal executables do. The permissions requirements
+to open a file O_EXEC are (a) no one has it open read/write and
+(b) that the open has execute permissions on the file.
+
Linux documentation for functions is transitioning to inline
documentation via specially-formatted comments near their
definitions in the source. These comments can be combined with the
diff -uNrX linux-ignore-files linux-2.4.12/arch/alpha/kernel/osf_sys.c linux-2.4.12.eb2/arch/alpha/kernel/osf_sys.c
--- linux-2.4.12/arch/alpha/kernel/osf_sys.c Sat Oct 13 16:18:56 2001
+++ linux-2.4.12.eb2/arch/alpha/kernel/osf_sys.c Sat Oct 13 17:15:04 2001
@@ -240,7 +240,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flags, off);
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/arch/arm/kernel/sys_arm.c linux-2.4.12.eb2/arch/arm/kernel/sys_arm.c
--- linux-2.4.12/arch/arm/kernel/sys_arm.c Wed Jul 25 03:08:24 2001
+++ linux-2.4.12.eb2/arch/arm/kernel/sys_arm.c Sat Oct 13 17:07:57 2001
@@ -58,7 +58,7 @@
int error = -EINVAL;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
/*
* If we are doing a fixed mapping, and address < PAGE_SIZE,
diff -uNrX linux-ignore-files linux-2.4.12/arch/cris/kernel/sys_cris.c linux-2.4.12.eb2/arch/cris/kernel/sys_cris.c
--- linux-2.4.12/arch/cris/kernel/sys_cris.c Sat Aug 11 09:50:04 2001
+++ linux-2.4.12.eb2/arch/cris/kernel/sys_cris.c Sat Oct 13 17:14:06 2001
@@ -52,7 +52,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/i386/kernel/sys_i386.c linux-2.4.12.eb2/arch/i386/kernel/sys_i386.c
--- linux-2.4.12/arch/i386/kernel/sys_i386.c Sat Apr 14 13:36:44 2001
+++ linux-2.4.12.eb2/arch/i386/kernel/sys_i386.c Sat Oct 13 17:08:07 2001
@@ -48,7 +48,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/ia64/ia32/sys_ia32.c linux-2.4.12.eb2/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.12/arch/ia64/ia32/sys_ia32.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb2/arch/ia64/ia32/sys_ia32.c Sat Oct 13 17:15:34 2001
@@ -282,7 +282,7 @@
long error = -EFAULT;
unsigned int poff;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
prot |= PROT_EXEC;
if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
diff -uNrX linux-ignore-files linux-2.4.12/arch/ia64/kernel/sys_ia64.c linux-2.4.12.eb2/arch/ia64/kernel/sys_ia64.c
--- linux-2.4.12/arch/ia64/kernel/sys_ia64.c Sat Aug 11 09:50:05 2001
+++ linux-2.4.12.eb2/arch/ia64/kernel/sys_ia64.c Sat Oct 13 17:10:39 2001
@@ -178,7 +178,7 @@
unsigned long roff;
struct file *file = 0;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/m68k/kernel/sys_m68k.c linux-2.4.12.eb2/arch/m68k/kernel/sys_m68k.c
--- linux-2.4.12/arch/m68k/kernel/sys_m68k.c Wed Jul 25 03:07:49 2001
+++ linux-2.4.12.eb2/arch/m68k/kernel/sys_m68k.c Sat Oct 13 17:11:13 2001
@@ -52,7 +52,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
@@ -104,7 +104,7 @@
if (a.offset & ~PAGE_MASK)
goto out;
- a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ a.flags &= ~(MAP_EXECUTABLE);
error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
out:
@@ -144,7 +144,7 @@
if (!file)
goto out;
}
- a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ a.flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips/kernel/irixelf.c linux-2.4.12.eb2/arch/mips/kernel/irixelf.c
--- linux-2.4.12/arch/mips/kernel/irixelf.c Sat Apr 14 13:36:44 2001
+++ linux-2.4.12.eb2/arch/mips/kernel/irixelf.c Sun Oct 14 00:35:14 2001
@@ -298,7 +298,7 @@
eppnt = elf_phdata;
for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
if(eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+ int elf_type = MAP_PRIVATE;
int elf_prot = 0;
unsigned long vaddr = 0;
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
@@ -479,7 +479,7 @@
return 0;
}
-#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE)
+#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE)
static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum,
unsigned int *estack, unsigned int *laddr,
@@ -776,7 +776,6 @@
return retval;
out_free_dentry:
- allow_write_access(interpreter);
fput(interpreter);
out_free_interp:
if (elf_interpreter)
@@ -842,7 +841,7 @@
elf_phdata->p_vaddr & 0xfffff000,
elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
elf_phdata->p_offset & 0xfffff000);
up_write(¤t->mm->mmap_sem);
@@ -919,7 +918,7 @@
down_write(¤t->mm->mmap_sem);
retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000),
(hp->p_filesz + (hp->p_vaddr & 0xfff)),
- prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
+ prot, (MAP_FIXED | MAP_PRIVATE),
(hp->p_offset & 0xfffff000));
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips/kernel/syscall.c linux-2.4.12.eb2/arch/mips/kernel/syscall.c
--- linux-2.4.12/arch/mips/kernel/syscall.c Wed Jul 25 03:07:50 2001
+++ linux-2.4.12.eb2/arch/mips/kernel/syscall.c Sat Oct 13 17:11:32 2001
@@ -62,7 +62,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips/kernel/sysirix.c linux-2.4.12.eb2/arch/mips/kernel/sysirix.c
--- linux-2.4.12/arch/mips/kernel/sysirix.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb2/arch/mips/kernel/sysirix.c Sat Oct 13 17:16:16 2001
@@ -1080,7 +1080,7 @@
}
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, offset);
@@ -1640,7 +1640,7 @@
}
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
diff -uNrX linux-ignore-files linux-2.4.12/arch/mips64/kernel/syscall.c linux-2.4.12.eb2/arch/mips64/kernel/syscall.c
--- linux-2.4.12/arch/mips64/kernel/syscall.c Sat Oct 13 16:19:43 2001
+++ linux-2.4.12.eb2/arch/mips64/kernel/syscall.c Sat Oct 13 17:11:45 2001
@@ -63,7 +63,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
error = do_mmap(file, addr, len, prot, flags, offset);
diff -uNrX linux-ignore-files linux-2.4.12/arch/parisc/kernel/sys_parisc.c linux-2.4.12.eb2/arch/parisc/kernel/sys_parisc.c
--- linux-2.4.12/arch/parisc/kernel/sys_parisc.c Sat Apr 14 13:36:45 2001
+++ linux-2.4.12.eb2/arch/parisc/kernel/sys_parisc.c Sat Oct 13 17:13:55 2001
@@ -59,7 +59,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
error = do_mmap(file, addr, len, prot, flags, offset);
if (file != NULL)
fput(file);
diff -uNrX linux-ignore-files linux-2.4.12/arch/ppc/kernel/syscalls.c linux-2.4.12.eb2/arch/ppc/kernel/syscalls.c
--- linux-2.4.12/arch/ppc/kernel/syscalls.c Wed Jul 25 03:07:25 2001
+++ linux-2.4.12.eb2/arch/ppc/kernel/syscalls.c Sat Oct 13 17:12:01 2001
@@ -196,7 +196,7 @@
struct file * file = NULL;
int ret = -EBADF;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
if (!(file = fget(fd)))
goto out;
diff -uNrX linux-ignore-files linux-2.4.12/arch/s390/kernel/sys_s390.c linux-2.4.12.eb2/arch/s390/kernel/sys_s390.c
--- linux-2.4.12/arch/s390/kernel/sys_s390.c Sat Apr 14 13:36:45 2001
+++ linux-2.4.12.eb2/arch/s390/kernel/sys_s390.c Sat Oct 13 17:13:33 2001
@@ -54,7 +54,7 @@
int error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/s390x/kernel/linux32.c linux-2.4.12.eb2/arch/s390x/kernel/linux32.c
--- linux-2.4.12/arch/s390x/kernel/linux32.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb2/arch/s390x/kernel/linux32.c Sat Oct 13 20:13:59 2001
@@ -2923,12 +2923,10 @@
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count32(argv)) < 0) {
- allow_write_access(file);
fput(file);
return bprm.argc;
}
if ((bprm.envc = count32(envp)) < 0) {
- allow_write_access(file);
fput(file);
return bprm.envc;
}
@@ -2957,7 +2955,6 @@
out:
/* Something went wrong, return the inode and free the argument pages*/
- allow_write_access(bprm.file);
if (bprm.file)
fput(bprm.file);
@@ -4179,7 +4176,7 @@
struct file * file = NULL;
unsigned long error = -EBADF;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/s390x/kernel/sys_s390.c linux-2.4.12.eb2/arch/s390x/kernel/sys_s390.c
--- linux-2.4.12/arch/s390x/kernel/sys_s390.c Thu May 3 01:46:43 2001
+++ linux-2.4.12.eb2/arch/s390x/kernel/sys_s390.c Sat Oct 13 17:14:23 2001
@@ -54,7 +54,7 @@
long error = -EBADF;
struct file * file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/sh/kernel/sys_sh.c linux-2.4.12.eb2/arch/sh/kernel/sys_sh.c
--- linux-2.4.12/arch/sh/kernel/sys_sh.c Sat Oct 13 16:19:45 2001
+++ linux-2.4.12.eb2/arch/sh/kernel/sys_sh.c Sat Oct 13 17:12:17 2001
@@ -89,7 +89,7 @@
int error = -EBADF;
struct file *file = NULL;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc/kernel/sys_sparc.c linux-2.4.12.eb2/arch/sparc/kernel/sys_sparc.c
--- linux-2.4.12/arch/sparc/kernel/sys_sparc.c Thu May 3 01:46:43 2001
+++ linux-2.4.12.eb2/arch/sparc/kernel/sys_sparc.c Sat Oct 13 17:12:40 2001
@@ -240,7 +240,7 @@
if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
goto out_putf;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc/kernel/sys_sunos.c linux-2.4.12.eb2/arch/sparc/kernel/sys_sunos.c
--- linux-2.4.12/arch/sparc/kernel/sys_sunos.c Sat Oct 13 16:18:57 2001
+++ linux-2.4.12.eb2/arch/sparc/kernel/sys_sunos.c Sun Oct 14 00:35:47 2001
@@ -115,7 +115,7 @@
goto out_putf;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, off);
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/binfmt_aout32.c linux-2.4.12.eb2/arch/sparc64/kernel/binfmt_aout32.c
--- linux-2.4.12/arch/sparc64/kernel/binfmt_aout32.c Wed Jul 25 03:08:26 2001
+++ linux-2.4.12.eb2/arch/sparc64/kernel/binfmt_aout32.c Sun Oct 14 00:36:22 2001
@@ -280,7 +280,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset);
up_write(¤t->mm->mmap_sem);
@@ -292,7 +292,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
up_write(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
@@ -372,7 +372,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
N_TXTOFF(ex));
up_write(¤t->mm->mmap_sem);
retval = error;
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/sys_sparc.c linux-2.4.12.eb2/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.12/arch/sparc64/kernel/sys_sparc.c Thu May 3 01:46:44 2001
+++ linux-2.4.12.eb2/arch/sparc64/kernel/sys_sparc.c Sat Oct 13 17:13:19 2001
@@ -277,7 +277,7 @@
if (!file)
goto out;
}
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
len = PAGE_ALIGN(len);
retval = -EINVAL;
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/sys_sparc32.c linux-2.4.12.eb2/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.12/arch/sparc64/kernel/sys_sparc32.c Sat Oct 13 16:21:40 2001
+++ linux-2.4.12.eb2/arch/sparc64/kernel/sys_sparc32.c Sat Oct 13 20:28:49 2001
@@ -2998,12 +2998,10 @@
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.argc;
}
if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.envc;
}
@@ -3032,7 +3030,6 @@
out:
/* Something went wrong, return the inode and free the argument pages*/
- allow_write_access(bprm.file);
if (bprm.file)
fput(bprm.file);
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/kernel/sys_sunos32.c linux-2.4.12.eb2/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.12/arch/sparc64/kernel/sys_sunos32.c Sat Oct 13 16:18:58 2001
+++ linux-2.4.12.eb2/arch/sparc64/kernel/sys_sunos32.c Sat Oct 13 17:16:57 2001
@@ -99,7 +99,7 @@
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
diff -uNrX linux-ignore-files linux-2.4.12/arch/sparc64/solaris/misc.c linux-2.4.12.eb2/arch/sparc64/solaris/misc.c
--- linux-2.4.12/arch/sparc64/solaris/misc.c Sat Oct 13 16:19:45 2001
+++ linux-2.4.12.eb2/arch/sparc64/solaris/misc.c Sat Oct 13 17:17:17 2001
@@ -93,7 +93,7 @@
flags &= ~_MAP_NEW;
down_write(¤t->mm->mmap_sem);
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ flags &= ~(MAP_EXECUTABLE);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
(unsigned long) prot, (unsigned long) flags, off);
Binary files linux-2.4.12/drivers/net/hamradio/soundmodem/gentbl and linux-2.4.12.eb2/drivers/net/hamradio/soundmodem/gentbl differ
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_aout.c linux-2.4.12.eb2/fs/binfmt_aout.c
--- linux-2.4.12/fs/binfmt_aout.c Sat Oct 13 16:21:50 2001
+++ linux-2.4.12.eb2/fs/binfmt_aout.c Sun Oct 14 00:59:39 2001
@@ -380,7 +380,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset);
up_write(¤t->mm->mmap_sem);
@@ -392,7 +392,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ MAP_FIXED | MAP_PRIVATE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
up_write(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
@@ -479,7 +479,7 @@
down_write(¤t->mm->mmap_sem);
error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
N_TXTOFF(ex));
up_write(¤t->mm->mmap_sem);
retval = error;
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_elf.c linux-2.4.12.eb2/fs/binfmt_elf.c
--- linux-2.4.12/fs/binfmt_elf.c Sat Oct 13 16:21:50 2001
+++ linux-2.4.12.eb2/fs/binfmt_elf.c Sun Oct 14 00:38:37 2001
@@ -288,7 +288,7 @@
eppnt = elf_phdata;
for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+ int elf_type = MAP_PRIVATE;
int elf_prot = 0;
unsigned long vaddr = 0;
unsigned long k, map_addr;
@@ -642,7 +642,7 @@
if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
- elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
+ elf_flags = MAP_PRIVATE|MAP_EXECUTABLE;
vaddr = elf_ppnt->p_vaddr;
if (elf_ex.e_type == ET_EXEC || load_addr_set) {
@@ -701,7 +701,6 @@
interpreter,
&interp_load_addr);
- allow_write_access(interpreter);
fput(interpreter);
kfree(elf_interpreter);
@@ -789,7 +788,6 @@
/* error cleanup */
out_free_dentry:
- allow_write_access(interpreter);
fput(interpreter);
out_free_interp:
if (elf_interpreter)
@@ -853,7 +851,7 @@
(elf_phdata->p_filesz +
ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ MAP_FIXED | MAP_PRIVATE,
(elf_phdata->p_offset -
ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
up_write(¤t->mm->mmap_sem);
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_em86.c linux-2.4.12.eb2/fs/binfmt_em86.c
--- linux-2.4.12/fs/binfmt_em86.c Sat Mar 17 16:28:29 2001
+++ linux-2.4.12.eb2/fs/binfmt_em86.c Sat Oct 13 20:12:38 2001
@@ -44,7 +44,6 @@
}
bprm->sh_bang++; /* Well, the bang-shell is implicit... */
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_misc.c linux-2.4.12.eb2/fs/binfmt_misc.c
--- linux-2.4.12/fs/binfmt_misc.c Sat Mar 17 16:28:29 2001
+++ linux-2.4.12.eb2/fs/binfmt_misc.c Sat Oct 13 20:12:46 2001
@@ -201,7 +201,6 @@
if (!fmt)
goto _ret;
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/binfmt_script.c linux-2.4.12.eb2/fs/binfmt_script.c
--- linux-2.4.12/fs/binfmt_script.c Sat Mar 17 16:28:29 2001
+++ linux-2.4.12.eb2/fs/binfmt_script.c Sat Oct 13 20:12:30 2001
@@ -29,7 +29,6 @@
*/
bprm->sh_bang++;
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/exec.c linux-2.4.12.eb2/fs/exec.c
--- linux-2.4.12/fs/exec.c Sat Oct 13 16:20:02 2001
+++ linux-2.4.12.eb2/fs/exec.c Sun Oct 14 00:19:53 2001
@@ -337,39 +337,7 @@
struct file *open_exec(const char *name)
{
- struct nameidata nd;
- struct inode *inode;
- struct file *file;
- int err = 0;
-
- if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
- err = path_walk(name, &nd);
- file = ERR_PTR(err);
- if (!err) {
- inode = nd.dentry->d_inode;
- file = ERR_PTR(-EACCES);
- if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
- S_ISREG(inode->i_mode)) {
- int err = permission(inode, MAY_EXEC);
- if (!err && !(inode->i_mode & 0111))
- err = -EACCES;
- file = ERR_PTR(err);
- if (!err) {
- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
- fput(file);
- file = ERR_PTR(err);
- }
- }
-out:
- return file;
- }
- }
- path_release(&nd);
- }
- goto out;
+ return filp_open(name, O_EXEC | O_RDONLY, 0);
}
int kernel_read(struct file *file, unsigned long offset,
@@ -774,7 +742,6 @@
struct file * file;
unsigned long loader;
- allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
@@ -809,7 +776,6 @@
retval = fn(bprm, regs);
if (retval >= 0) {
put_binfmt(fmt);
- allow_write_access(bprm->file);
if (bprm->file)
fput(bprm->file);
bprm->file = NULL;
@@ -871,13 +837,11 @@
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.argc;
}
if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {
- allow_write_access(file);
fput(file);
return bprm.envc;
}
@@ -906,7 +870,6 @@
out:
/* Something went wrong, return the inode and free the argument pages*/
- allow_write_access(bprm.file);
if (bprm.file)
fput(bprm.file);
diff -uNrX linux-ignore-files linux-2.4.12/fs/file_table.c linux-2.4.12.eb2/fs/file_table.c
--- linux-2.4.12/fs/file_table.c Sat Oct 13 16:20:02 2001
+++ linux-2.4.12.eb2/fs/file_table.c Sat Oct 13 20:00:23 2001
@@ -114,6 +114,8 @@
fops_put(file->f_op);
if (file->f_mode & FMODE_WRITE)
put_write_access(inode);
+ if (file->f_mode & FMODE_EXEC)
+ allow_write_access(inode);
file_list_lock();
file->f_dentry = NULL;
file->f_vfsmnt = NULL;
diff -uNrX linux-ignore-files linux-2.4.12/fs/namei.c linux-2.4.12.eb2/fs/namei.c
--- linux-2.4.12/fs/namei.c Sat Oct 13 16:22:01 2001
+++ linux-2.4.12.eb2/fs/namei.c Sun Oct 14 00:40:39 2001
@@ -212,10 +212,10 @@
* put_write_access() releases this write permission.
* This is used for regular files.
* We cannot support write (and maybe mmap read-write shared) accesses and
- * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
- * can have the following values:
- * 0: no writers, no VM_DENYWRITE mappings
- * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
+ * O_EXEC mmappings simultaneously. The i_writecount field of an inode can have
+ * the following values:
+ * 0: no writers, no executers.
+ * < 0: (-i_writecount) users are executing the file.
* > 0: (i_writecount) users are writing to the file.
*
* Normally we operate on that counter with atomic_{inc,dec} and it's safe
@@ -974,6 +974,8 @@
int count = 0;
acc_mode = ACC_MODE(flag);
+ if (flag & O_EXEC)
+ acc_mode |= MAY_EXEC;
/*
* The simplest case - just a plain lookup.
@@ -1065,10 +1067,22 @@
error = -ELOOP;
if (S_ISLNK(inode->i_mode))
goto exit;
-
+
error = -EISDIR;
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
goto exit;
+
+ error = -EACCES;
+ if (flag & O_EXEC) {
+ if (flag & FMODE_WRITE)
+ goto exit;
+ if (nd.mnt->mnt_flags & MNT_NOEXEC)
+ goto exit;
+ if (!S_ISREG(inode->i_mode))
+ goto exit;
+ if (!(inode->i_mode & S_IXUGO))
+ goto exit;
+ }
error = permission(inode,acc_mode);
if (error)
diff -uNrX linux-ignore-files linux-2.4.12/fs/open.c linux-2.4.12.eb2/fs/open.c
--- linux-2.4.12/fs/open.c Sat Oct 13 16:21:50 2001
+++ linux-2.4.12.eb2/fs/open.c Sun Oct 14 00:08:27 2001
@@ -644,6 +644,8 @@
goto cleanup_dentry;
f->f_flags = flags;
f->f_mode = (flags+1) & O_ACCMODE;
+ if (flags & O_EXEC)
+ f->f_mode |= FMODE_EXEC;
inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
@@ -673,6 +675,12 @@
goto cleanup_all;
}
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+
+ if (f->f_mode & FMODE_EXEC) {
+ error = deny_write_access(f);
+ if (error)
+ goto cleanup_all;
+ }
return f;
diff -uNrX linux-ignore-files linux-2.4.12/include/asm-i386/fcntl.h linux-2.4.12.eb2/include/asm-i386/fcntl.h
--- linux-2.4.12/include/asm-i386/fcntl.h Sat Oct 13 16:20:04 2001
+++ linux-2.4.12.eb2/include/asm-i386/fcntl.h Sun Oct 14 00:08:01 2001
@@ -7,6 +7,7 @@
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
+#define O_EXEC 04 /* generate ETXTBSY on writes */
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
diff -uNrX linux-ignore-files linux-2.4.12/include/linux/fs.h linux-2.4.12.eb2/include/linux/fs.h
--- linux-2.4.12/include/linux/fs.h Sat Oct 13 17:26:25 2001
+++ linux-2.4.12.eb2/include/linux/fs.h Sun Oct 14 00:42:30 2001
@@ -73,6 +73,7 @@
#define FMODE_READ 1
#define FMODE_WRITE 2
+#define FMODE_EXEC 4
#define READ 0
#define WRITE 1
diff -uNrX linux-ignore-files linux-2.4.12/kernel/fork.c linux-2.4.12.eb2/kernel/fork.c
--- linux-2.4.12/kernel/fork.c Sat Oct 13 16:20:09 2001
+++ linux-2.4.12.eb2/kernel/fork.c Sat Oct 13 20:34:56 2001
@@ -168,8 +168,6 @@
if (file) {
struct inode *inode = file->f_dentry->d_inode;
get_file(file);
- if (tmp->vm_flags & VM_DENYWRITE)
- atomic_dec(&inode->i_writecount);
/* insert tmp into the share list, just after mpnt */
spin_lock(&inode->i_mapping->i_shared_lock);
diff -uNrX linux-ignore-files linux-2.4.12/mm/mmap.c linux-2.4.12.eb2/mm/mmap.c
--- linux-2.4.12/mm/mmap.c Sat Oct 13 16:21:52 2001
+++ linux-2.4.12.eb2/mm/mmap.c Sun Oct 14 00:50:32 2001
@@ -98,9 +98,6 @@
struct file * file = vma->vm_file;
if (file) {
- struct inode *inode = file->f_dentry->d_inode;
- if (vma->vm_flags & VM_DENYWRITE)
- atomic_inc(&inode->i_writecount);
if(vma->vm_next_share)
vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
*vma->vm_pprev_share = vma->vm_next_share;
@@ -205,7 +202,6 @@
_trans(prot, PROT_EXEC, VM_EXEC);
flag_bits =
_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) |
- _trans(flags, MAP_DENYWRITE, VM_DENYWRITE) |
_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE);
return prot_bits | flag_bits;
#undef _trans
@@ -310,9 +306,6 @@
struct address_space *mapping = inode->i_mapping;
struct vm_area_struct **head;
- if (vma->vm_flags & VM_DENYWRITE)
- atomic_dec(&inode->i_writecount);
-
head = &mapping->i_mmap;
if (vma->vm_flags & VM_SHARED)
head = &mapping->i_mmap_shared;
@@ -395,7 +388,6 @@
struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev;
unsigned int vm_flags;
- int correct_wcount = 0;
int error;
rb_node_t ** rb_link, * rb_parent;
@@ -526,12 +518,6 @@
error = -EINVAL;
if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
goto free_vma;
- if (vm_flags & VM_DENYWRITE) {
- error = deny_write_access(file);
- if (error)
- goto free_vma;
- correct_wcount = 1;
- }
vma->vm_file = file;
get_file(file);
error = file->f_op->mmap(file, vma);
@@ -551,8 +537,6 @@
addr = vma->vm_start;
vma_link(mm, vma, prev, rb_link, rb_parent);
- if (correct_wcount)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
out:
mm->total_vm += len >> PAGE_SHIFT;
@@ -563,8 +547,6 @@
return addr;
unmap_and_free_vma:
- if (correct_wcount)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
vma->vm_file = NULL;
fput(file);
@@ -946,11 +928,9 @@
* so release them, and unmap the page range..
* If the one of the segments is only being partially unmapped,
* it will put new vm_area_struct(s) into the address space.
- * In that case we have to be careful with VM_DENYWRITE.
*/
while ((mpnt = free) != NULL) {
unsigned long st, end, size;
- struct file *file = NULL;
free = free->vm_next;
@@ -959,11 +939,6 @@
end = end > mpnt->vm_end ? mpnt->vm_end : end;
size = end - st;
- if (mpnt->vm_flags & VM_DENYWRITE &&
- (st != mpnt->vm_start || end != mpnt->vm_end) &&
- (file = mpnt->vm_file) != NULL) {
- atomic_dec(&file->f_dentry->d_inode->i_writecount);
- }
remove_shared_vm_struct(mpnt);
mm->map_count--;
@@ -973,8 +948,6 @@
* Fix the mapping, and free the old area if it wasn't reused.
*/
extra = unmap_fixup(mm, mpnt, st, size, extra);
- if (file)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
}
validate_mm(mm);
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2001-10-15 12:11 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-10-14 14:50 [RFC] "Text file busy" when overwriting libraries Samium Gromoff
-- strict thread matches above, loose matches on Subject: below --
2001-10-05 16:58 Security question: "Text file busy" overwriting executables but Linus Torvalds
2001-10-14 8:02 ` [RFC] "Text file busy" when overwriting libraries Eric W. Biederman
2001-10-14 12:08 ` Alan Cox
2001-10-14 20:48 ` Eric W. Biederman
2001-10-15 1:44 ` Alan Cox
2001-10-15 2:06 ` Linus Torvalds
2001-10-15 10:11 ` Eric W. Biederman
2001-10-15 11:54 ` Alan Cox
2001-10-15 11:57 ` Alexander Viro
2001-10-15 12:08 ` Alan Cox
2001-10-15 12:11 ` Alexander Viro
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®