Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131641459
D32611.id97418.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D32611.id97418.diff
View Options
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -241,9 +241,9 @@
#ifndef _SYS_SYSPROTO_H_
struct execve_args {
- char *fname;
+ char *fname;
char **argv;
- char **envv;
+ char **envv;
};
#endif
@@ -420,11 +420,13 @@
#ifdef KTRACE
struct ktr_io_params *kiop;
#endif
- struct vnode *oldtextvp = NULL, *newtextvp;
- int credential_changing;
+ struct vnode *oldtextvp, *newtextvp;
+ struct vnode *oldtextdvp, *newtextdvp;
+ char *oldbinname, *newbinname;
+ bool credential_changing;
#ifdef MAC
struct label *interpvplabel = NULL;
- int will_transition;
+ bool will_transition;
#endif
#ifdef HWPMC_HOOKS
struct pmckern_procexec pe;
@@ -432,9 +434,13 @@
int error, i, orig_osrel;
uint32_t orig_fctl0;
Elf_Brandinfo *orig_brandinfo;
+ size_t freepath_size;
static const char fexecv_proc_title[] = "(fexecv)";
imgp = &image_params;
+ oldtextvp = oldtextdvp = NULL;
+ newtextvp = newtextdvp = NULL;
+ newbinname = oldbinname = NULL;
#ifdef KTRACE
kiop = NULL;
#endif
@@ -470,18 +476,6 @@
goto exec_fail;
#endif
- /*
- * Translate the file name. namei() returns a vnode pointer
- * in ni_vp among other things.
- *
- * XXXAUDIT: It would be desirable to also audit the name of the
- * interpreter if this is an interpreted binary.
- */
- if (args->fname != NULL) {
- NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
- SAVENAME | AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
- }
-
SDT_PROBE1(proc, , , exec, args->fname);
interpret:
@@ -498,20 +492,53 @@
goto exec_fail;
}
#endif
+
+ /*
+ * Translate the file name. namei() returns a vnode
+ * pointer in ni_vp among other things.
+ */
+ NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
+ SAVENAME | AUDITVNODE1 | WANTPARENT, UIO_SYSSPACE,
+ args->fname, td);
+
error = namei(&nd);
if (error)
goto exec_fail;
newtextvp = nd.ni_vp;
+ newtextdvp = nd.ni_dvp;
+ newbinname = malloc(nd.ni_cnd.cn_namelen + 1, M_PARGS,
+ M_WAITOK);
+ memcpy(newbinname, nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen);
+ newbinname[nd.ni_cnd.cn_namelen] = '\0';
imgp->vp = newtextvp;
+
+ /*
+ * Do the best to calculate the full path to the image file.
+ */
+ if (args->fname[0] == '/') {
+ imgp->execpath = args->fname;
+ } else {
+ VOP_UNLOCK(imgp->vp);
+ freepath_size = MAXPATHLEN;
+ if (vn_fullpath_hardlink(&nd, &imgp->execpath,
+ &imgp->freepath, &freepath_size) != 0)
+ imgp->execpath = args->fname;
+ vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
+ }
+ nd.ni_dvp = NULL;
} else {
AUDIT_ARG_FD(args->fd);
/*
* Descriptors opened only with O_EXEC or O_RDONLY are allowed.
*/
- error = fgetvp_exec(td, args->fd, &cap_fexecve_rights, &newtextvp);
+ error = fgetvp_exec(td, args->fd, &cap_fexecve_rights,
+ &newtextvp);
if (error)
goto exec_fail;
+ if (vn_fullpath(imgp->vp, &imgp->execpath,
+ &imgp->freepath) != 0)
+ imgp->execpath = args->fname;
vn_lock(newtextvp, LK_SHARED | LK_RETRY);
AUDIT_ARG_VNODE1(newtextvp);
imgp->vp = newtextvp;
@@ -557,14 +584,14 @@
* XXXMAC: For the time being, use NOSUID to also prohibit
* transitions on the file system.
*/
- credential_changing = 0;
+ credential_changing = false;
credential_changing |= (attr.va_mode & S_ISUID) &&
oldcred->cr_uid != attr.va_uid;
credential_changing |= (attr.va_mode & S_ISGID) &&
oldcred->cr_gid != attr.va_gid;
#ifdef MAC
will_transition = mac_vnode_execve_will_transition(oldcred, imgp->vp,
- interpvplabel, imgp);
+ interpvplabel, imgp) != 0;
credential_changing |= will_transition;
#endif
@@ -621,18 +648,6 @@
}
/* The new credentials are installed into the process later. */
- /*
- * Do the best to calculate the full path to the image file.
- */
- if (args->fname != NULL && args->fname[0] == '/')
- imgp->execpath = args->fname;
- else {
- VOP_UNLOCK(imgp->vp);
- if (vn_fullpath(imgp->vp, &imgp->execpath, &imgp->freepath) != 0)
- imgp->execpath = args->fname;
- vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
- }
-
/*
* If the current process has a special image activator it
* wants to try first, call it. For example, emulating shell
@@ -678,16 +693,24 @@
VOP_UNSET_TEXT_CHECKED(newtextvp);
imgp->textset = false;
/* free name buffer and old vnode */
- if (args->fname != NULL)
- NDFREE(&nd, NDF_ONLY_PNBUF);
#ifdef MAC
mac_execve_interpreter_enter(newtextvp, &interpvplabel);
#endif
if (imgp->opened) {
VOP_CLOSE(newtextvp, FREAD, td->td_ucred, td);
- imgp->opened = 0;
+ imgp->opened = false;
}
vput(newtextvp);
+ newtextvp = NULL;
+ if (args->fname != NULL) {
+ if (newtextdvp != NULL) {
+ vrele(newtextdvp);
+ newtextdvp = NULL;
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ free(newbinname, M_PARGS);
+ newbinname = NULL;
+ }
vm_object_deallocate(imgp->object);
imgp->object = NULL;
execve_nosetid(imgp);
@@ -695,8 +718,6 @@
free(imgp->freepath, M_TEMP);
imgp->freepath = NULL;
/* set new name to that of the interpreter */
- NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
- SAVENAME, UIO_SYSSPACE, imgp->interpreter_name, td);
args->fname = imgp->interpreter_name;
goto interpret;
}
@@ -858,11 +879,17 @@
}
/*
- * Store the vp for use in procfs. This vnode was referenced by namei
- * or fgetvp_exec.
+ * Store the vp for use in kern.proc.pathname. This vnode was
+ * referenced by namei or fgetvp_exec.
*/
oldtextvp = p->p_textvp;
p->p_textvp = newtextvp;
+ oldtextdvp = p->p_textdvp;
+ p->p_textdvp = newtextdvp;
+ newtextdvp = NULL;
+ oldbinname = p->p_binname;
+ p->p_binname = newbinname;
+ newbinname = NULL;
#ifdef KDTRACE_HOOKS
/*
@@ -928,8 +955,6 @@
exec_unmap_first_page(imgp);
if (imgp->vp != NULL) {
- if (args->fname)
- NDFREE(&nd, NDF_ONLY_PNBUF);
if (imgp->opened)
VOP_CLOSE(imgp->vp, FREAD, td->td_ucred, td);
if (imgp->textset)
@@ -938,6 +963,11 @@
vput(imgp->vp);
else
VOP_UNLOCK(imgp->vp);
+ if (args->fname != NULL)
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ if (newtextdvp != NULL)
+ vrele(newtextdvp);
+ free(newbinname, M_PARGS);
}
if (imgp->object != NULL)
@@ -976,6 +1006,9 @@
*/
if (oldtextvp != NULL)
vrele(oldtextvp);
+ if (oldtextdvp != NULL)
+ vrele(oldtextdvp);
+ free(oldbinname, M_PARGS);
#ifdef KTRACE
ktr_io_params_free(kiop);
#endif
@@ -1040,7 +1073,7 @@
#endif
error = vm_page_grab_valid_unlocked(&m, object, 0,
VM_ALLOC_COUNT(VM_INITIAL_PAGEIN) |
- VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY | VM_ALLOC_WIRED);
+ VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY | VM_ALLOC_WIRED);
if (error != VM_PAGER_OK)
return (EIO);
@@ -1089,7 +1122,7 @@
vm_prot_t stack_prot;
u_long ssiz;
- imgp->vmspace_destroyed = 1;
+ imgp->vmspace_destroyed = true;
imgp->sysent = sv;
if (p->p_sysent->sv_onexec_old != NULL)
@@ -1789,7 +1822,7 @@
*/
error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL);
if (error == 0)
- imgp->opened = 1;
+ imgp->opened = true;
return (error);
}
@@ -1985,7 +2018,8 @@
if (locked)
PROC_UNLOCK(p);
if (cp->comp != NULL)
- error = compressor_write(cp->comp, __DECONST(char *, data), len);
+ error = compressor_write(cp->comp, __DECONST(char *, data),
+ len);
else
error = core_write(cp, __DECONST(void *, data), len, cp->offset,
UIO_SYSSPACE, NULL);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -424,12 +424,20 @@
ktrprocexit(td);
#endif
/*
- * Release reference to text vnode
+ * Release reference to text vnode etc
*/
if (p->p_textvp != NULL) {
vrele(p->p_textvp);
p->p_textvp = NULL;
}
+ if (p->p_textdvp != NULL) {
+ vrele(p->p_textdvp);
+ p->p_textdvp = NULL;
+ }
+ if (p->p_binname != NULL) {
+ free(p->p_binname, M_PARGS);
+ p->p_binname = NULL;
+ }
/*
* Release our limits structure.
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -528,6 +528,7 @@
}
p2->p_textvp = p1->p_textvp;
+ p2->p_textdvp = p1->p_textdvp;
p2->p_fd = fd;
p2->p_fdtol = fdtol;
p2->p_pd = pd;
@@ -549,9 +550,16 @@
PROC_UNLOCK(p1);
PROC_UNLOCK(p2);
- /* Bump references to the text vnode (for procfs). */
- if (p2->p_textvp)
+ /*
+ * Bump references to the text vnode and directory, and copy
+ * the hardlink name.
+ */
+ if (p2->p_textvp != NULL)
vrefact(p2->p_textvp);
+ if (p2->p_textdvp != NULL)
+ vrefact(p2->p_textdvp);
+ p2->p_binname = p1->p_binname == NULL ? NULL :
+ strdup(p1->p_binname, M_PARGS);
/*
* Set up linkage for kernel based threading.
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -45,6 +45,7 @@
#include <sys/elf.h>
#include <sys/eventhandler.h>
#include <sys/exec.h>
+#include <sys/fcntl.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/limits.h>
@@ -54,6 +55,7 @@
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/mutex.h>
+#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/refcount.h>
@@ -2233,32 +2235,78 @@
pid_t *pidp = (pid_t *)arg1;
unsigned int arglen = arg2;
struct proc *p;
- struct vnode *vp;
- char *retbuf, *freebuf;
+ struct vnode *vp, *dvp;
+ char *retbuf, *freebuf, *binname;
+ struct nameidata nd;
+ size_t freepath_size;
int error;
+ bool do_fullpath;
if (arglen != 1)
return (EINVAL);
+ binname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ binname[0] = '\0';
if (*pidp == -1) { /* -1 means this process */
p = req->td->td_proc;
} else {
error = pget(*pidp, PGET_CANSEE, &p);
- if (error != 0)
+ if (error != 0) {
+ free(binname, M_TEMP);
return (error);
+ }
}
vp = p->p_textvp;
if (vp == NULL) {
if (*pidp != -1)
PROC_UNLOCK(p);
+ free(binname, M_TEMP);
return (0);
}
vref(vp);
+ dvp = p->p_textdvp;
+ if (dvp != NULL)
+ vref(dvp);
+ if (p->p_binname != NULL)
+ strlcpy(binname, p->p_binname, MAXPATHLEN);
if (*pidp != -1)
PROC_UNLOCK(p);
- error = vn_fullpath(vp, &retbuf, &freebuf);
+ do_fullpath = true;
+ if (dvp != NULL && binname[0] != '\0') {
+ freepath_size = MAXPATHLEN;
+ nd.ni_vp = vp;
+ nd.ni_dvp = dvp;
+ nd.ni_cnd.cn_nameptr = binname;
+ nd.ni_cnd.cn_namelen = strlen(binname);
+ if (vn_fullpath_hardlink(&nd, &retbuf, &freebuf,
+ &freepath_size) == 0) {
+ /*
+ * Recheck the looked up path. The binary
+ * might have been renamed or replaced, in
+ * which case we should not report old name.
+ */
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, retbuf,
+ req->td);
+ error = namei(&nd);
+ if (error == 0) {
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ if (nd.ni_vp == vp) {
+ do_fullpath = false;
+ } else {
+ free(freebuf, M_TEMP);
+ freebuf = NULL;
+ }
+ vrele(nd.ni_vp);
+ }
+ }
+ }
+ if (do_fullpath)
+ error = vn_fullpath(vp, &retbuf, &freebuf);
vrele(vp);
- if (error)
+ if (dvp != NULL)
+ vrele(dvp);
+ free(binname, M_TEMP);
+ if (error != 0)
return (error);
error = SYSCTL_OUT(req, retbuf, strlen(retbuf) + 1);
free(freebuf, M_TEMP);
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -97,11 +97,11 @@
"struct proc KBI p_flag");
_Static_assert(offsetof(struct proc, p_pid) == 0xc4,
"struct proc KBI p_pid");
-_Static_assert(offsetof(struct proc, p_filemon) == 0x3b8,
+_Static_assert(offsetof(struct proc, p_filemon) == 0x3c8,
"struct proc KBI p_filemon");
-_Static_assert(offsetof(struct proc, p_comm) == 0x3d0,
+_Static_assert(offsetof(struct proc, p_comm) == 0x3e0,
"struct proc KBI p_comm");
-_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b8,
+_Static_assert(offsetof(struct proc, p_emuldata) == 0x4c8,
"struct proc KBI p_emuldata");
#endif
#ifdef __i386__
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -579,8 +579,6 @@
"Number of times 3-way vnode locking failed");
static void cache_zap_locked(struct namecache *ncp);
-static int vn_fullpath_hardlink(struct nameidata *ndp, char **retbuf,
- char **freebuf, size_t *buflen);
static int vn_fullpath_any_smr(struct vnode *vp, struct vnode *rdir, char *buf,
char **retbuf, size_t *buflen, size_t addend);
static int vn_fullpath_any(struct vnode *vp, struct vnode *rdir, char *buf,
@@ -3602,7 +3600,7 @@
* - otherwise we populate the buffer with the saved name and start resolving
* from the parent
*/
-static int
+int
vn_fullpath_hardlink(struct nameidata *ndp, char **retbuf, char **freebuf,
size_t *buflen)
{
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -58,21 +58,16 @@
};
struct image_params {
- struct proc *proc; /* our process struct */
+ struct proc *proc; /* our process */
struct label *execlabel; /* optional exec label */
- struct vnode *vp; /* pointer to vnode of file to exec */
+ struct vnode *vp; /* pointer to vnode of file to exec */
struct vm_object *object; /* The vm object for this vp */
- struct vattr *attr; /* attributes of file */
- const char *image_header; /* head of file to exec */
- unsigned long entry_addr; /* entry address of target executable */
- unsigned long reloc_base; /* load address of image */
- char vmspace_destroyed; /* flag - we've blown away original vm space */
-#define IMGACT_SHELL 0x1
-#define IMGACT_BINMISC 0x2
- unsigned char interpreted; /* mask of interpreters that have run */
- char opened; /* flag - we have opened executable vnode */
- char *interpreter_name; /* name of the interpreter */
- void *auxargs; /* ELF Auxinfo structure pointer */
+ struct vattr *attr; /* attributes of file */
+ const char *image_header; /* header of file to exec */
+ unsigned long entry_addr; /* entry address of target executable */
+ unsigned long reloc_base; /* load address of image */
+ char *interpreter_name; /* name of the interpreter */
+ void *auxargs; /* ELF Auxinfo structure pointer */
struct sf_buf *firstpage; /* first page that we mapped */
void *ps_strings; /* pointer to ps_string (user space) */
struct image_args *args; /* system call arguments */
@@ -90,7 +85,12 @@
u_long stack_sz;
u_long eff_stack_sz;
struct ucred *newcred; /* new credentials if changing */
+#define IMGACT_SHELL 0x1
+#define IMGACT_BINMISC 0x2
+ unsigned char interpreted; /* mask of interpreters that have run */
bool credential_setid; /* true if becoming setid */
+ bool vmspace_destroyed; /* we've blown away original vm space */
+ bool opened; /* we have opened executable vnode */
bool textset;
u_int map_flags;
};
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -666,6 +666,8 @@
int p_traceflag; /* (o) Kernel trace points. */
struct ktr_io_params *p_ktrioparms; /* (c + o) Params for ktrace. */
struct vnode *p_textvp; /* (b) Vnode of executable. */
+ struct vnode *p_textdvp; /* (b) Dir containing textvp. */
+ char *p_binname; /* (b) Binary hardlink name. */
u_int p_lock; /* (c) Proclock (prevent swap) count. */
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
int p_sigparent; /* (c) Signal to parent on exit. */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -697,6 +697,8 @@
int vn_getcwd(char *buf, char **retbuf, size_t *buflen);
int vn_fullpath(struct vnode *vp, char **retbuf, char **freebuf);
int vn_fullpath_global(struct vnode *vp, char **retbuf, char **freebuf);
+int vn_fullpath_hardlink(struct nameidata *ndp, char **retbuf,
+ char **freebuf, size_t *buflen);
struct vnode *
vn_dir_dd_ino(struct vnode *vp);
int vn_commname(struct vnode *vn, char *buf, u_int buflen);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 10, 11:37 PM (2 m, 22 s ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23553094
Default Alt Text
D32611.id97418.diff (15 KB)
Attached To
Mode
D32611: exec: provide right hardlink name in AT_EXECPATH
Attached
Detach File
Event Timeline
Log In to Comment