summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Fiddaman <andy@omniosce.org>2020-09-16 16:23:43 +0100
committerGitHub <noreply@github.com>2020-09-16 11:23:43 -0400
commit73fb888b08574ef1b33df70ad8f9adc7f2508b41 (patch)
tree99114ab5021f127f44692abf7ea644ff308f3a51
parent51be84da33ce29cf2c4740ec15b1cdb43c83d9ae (diff)
downloadillumos-joyent-73fb888b08574ef1b33df70ad8f9adc7f2508b41.tar.gz
OS-8233 LX: readlink("/proc/<pid>/exe") can fail (#318)
Reviewed by: Mike Zeller <mike.zeller@joyent.com> Approved by: Jason King <jason.king@joyent.com>
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prvnops.c79
1 files changed, 71 insertions, 8 deletions
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
index c44c32ef29..575acd59a2 100644
--- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
+++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
@@ -22,6 +22,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2019 Joyent, Inc.
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
*/
/*
@@ -470,7 +471,7 @@ typedef struct lxpr_rlimtab {
char *rlim_rctl; /* rctl source */
} lxpr_rlimtab_t;
-#define RLIM_MAXFD "Max open files"
+#define RLIM_MAXFD "Max open files"
static lxpr_rlimtab_t lxpr_rlimtab[] = {
{ "Max cpu time", "seconds", "process.max-cpu-time" },
@@ -1737,8 +1738,9 @@ lxpr_read_pid_limits(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* match the max value so that we do not output "unlimited".
*/
if (strcmp(lxpr_rlimtab[i].rlim_name, RLIM_MAXFD) == 0 &&
- cur[i] == RLIM_INFINITY)
- cur[i] = max[i];
+ cur[i] == RLIM_INFINITY) {
+ cur[i] = max[i];
+ }
}
lxpr_unlock(p);
@@ -4001,10 +4003,10 @@ lxpr_read_meminfo(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* model, so just inform the caller that no swap is being used.
*
* MemAvailable
- * MemAvailable entry is available since Linux Kernel +3.14, is an
- * estimate of how much memory is available for starting new applications,
- * without swapping. In lxbrand we will always return the available free
- * memory as an estimate of this value.
+ * MemAvailable entry is available since Linux Kernel +3.14, is an
+ * estimate of how much memory is available for starting new
+ * applications, without swapping. In lxbrand we will always return the
+ * available free memory as an estimate of this value.
*/
lxpr_uiobuf_printf(uiobuf,
"MemTotal: %8lu kB\n"
@@ -8094,6 +8096,58 @@ lxpr_write_pid_loginuid(lxpr_node_t *lxpnp, struct uio *uio, struct cred *cr,
return (0);
}
+static int
+lxpr_readlink_exe(lxpr_node_t *lxpnp, char *buf, size_t size, cred_t *cr)
+{
+ size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
+ dirent64_t *dp;
+ vnode_t *dirvp;
+ int error = ENOENT;
+ char *dbuf;
+ proc_t *p;
+ size_t len;
+
+ p = lxpr_lock(lxpnp, NO_ZOMB);
+
+ if (p == NULL)
+ return (error);
+
+ dirvp = p->p_execdir;
+ if (dirvp == NULL) {
+ lxpr_unlock(p);
+ return (error);
+ }
+
+ VN_HOLD(dirvp);
+ lxpr_unlock(p);
+
+ /* Look up the parent directory path */
+ if ((error = vnodetopath(NULL, dirvp, buf, size, cr)) != 0) {
+ VN_RELE(dirvp);
+ return (error);
+ }
+
+ len = strlen(buf);
+
+ dbuf = kmem_alloc(dlen, KM_SLEEP);
+
+ /*
+ * Walk the parent directory to find the vnode for p->p_exec, in order
+ * to derive its path.
+ */
+ if ((error = dirfindvp(NULL, dirvp, lxpnp->lxpr_realvp,
+ cr, dbuf, dlen, &dp)) == 0 &&
+ strlen(dp->d_name) + len + 1 < size) {
+ buf[len] = '/';
+ (void) strcpy(buf + len + 1, dp->d_name);
+ } else {
+ error = ENOENT;
+ }
+ VN_RELE(dirvp);
+ kmem_free(dbuf, dlen);
+ return (error);
+}
+
/*
* lxpr_readlink(): Vnode operation for VOP_READLINK()
*/
@@ -8135,7 +8189,16 @@ lxpr_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
if (error != 0)
return (error);
- if ((error = vnodetopath(NULL, rvp, bp, buflen, cr)) != 0) {
+ error = vnodetopath(NULL, rvp, bp, buflen, cr);
+
+ /*
+ * Special handling for /proc/<pid>/exe where the vnode path is
+ * not cached.
+ */
+ if (error != 0 && lxpnp->lxpr_type == LXPR_PID_EXE)
+ error = lxpr_readlink_exe(lxpnp, bp, buflen, cr);
+
+ if (error != 0) {
/*
* Special handling possible for /proc/<pid>/fd/<num>
* Generate <type>:[<inode>] links, if allowed.