Bug 37554 - [vm] [patch] make ELF shared libraries immutable once loaded (like executables)
Summary: [vm] [patch] make ELF shared libraries immutable once loaded (like executables)
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
Depends on:
Reported: 2002-04-29 09:20 UTC by Peter Edwards
Modified: 2017-12-31 22:29 UTC (History)
0 users

See Also:

shlib-textbusy.tar.Z (2.85 KB, text/plain)
2002-04-29 09:20 UTC, Peter Edwards
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Edwards 2002-04-29 09:20:01 UTC
Before executing a program, the kernel marks the executable file as
immutable by setting the VTEXT flag in its vnode. This makes write
operations return with ETXTBSY when attempted.

However, no such flag is set for shared libraries mapped by rtld.

This patch adds a new fcntl command, F_TXTBSY, which sets the VTEXT flag
in the vnode associated with the file, and gets rtld-elf to make use
of it.

There may be security issues here, allowing user code to set this flag
in contexts it wasn't designed for, but I don't think it allows you do
anything that you couldn't already. You can't stop someone creating a
custom executable in order to get VTEXT set on it anyway, and root can
always kill any processes holding the object in memory to clear the
flag if neccessary.

Fix: Apply the following patch.
How-To-Repeat: Write a program that depends on a shared library, and overwrite that
library while the program is running. Bad Things happen.

Trying the same on an executable results in the write operation
returning ETXTBSY
Comment 1 Peter Edwards 2002-06-13 20:19:11 UTC
Hm. This is possibly a nicer way to do it, and certainly a smaller, if more 
intrusive, patch. It changes the semantics of mmap() somewhat, but I think 
in a reasonable way, and it avoids all that ugliness in the run-time linker.

Basically, a request for PROT_EXEC on a regular file will cause it to become 

--- vm_mmap.c   3 Nov 2001 01:41:10 -0000
+++ vm_mmap.c   13 Jun 2002 19:15:28 -0000
@@ -406,8 +406,17 @@

         error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
             flags, handle, pos);
-       if (error == 0)
+       if (error == 0) {
                 p->p_retval[0] = (register_t) (addr + pageoff);
+               /*
+                * A successful map for a regular file, with execute access:
+                * mark the vnode immutable.
+                * XXX: GCC warns, but (handle == 0 || handle == vp)
+                * I'm not sure of the "correct" way to avoid this.
+                */
+               if (handle && vp->v_type == VREG && (prot & PROT_EXEC))
+                       vp->v_flag |= VTEXT;
+       }
         if (fp)
                 fdrop(fp, p);

Of course, the utility of all this is questionable: I just wanted the 
functionality for something locally.
Comment 2 John-Mark Gurney freebsd_committer 2003-09-16 02:05:46 UTC
Responsible Changed
From-To: freebsd-bugs->jmg

I'm going to take this, since I'm interested in it.
Comment 3 Eitan Adler freebsd_committer freebsd_triage 2012-11-04 04:53:18 UTC
Responsible Changed
From-To: jmg->freebsd-bugs

no progress from jmg since 2003
Comment 4 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 07:59:13 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped