Page MenuHomeFreeBSD

D32611.id97418.diff
No OneTemporary

D32611.id97418.diff

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

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)

Event Timeline