diff options
Diffstat (limited to 'usr/src')
36 files changed, 2270 insertions, 495 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c index a6249ae566..b685612b40 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c +++ b/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c @@ -24,7 +24,7 @@ * netstat.c 2.2, last change 9/9/91 * MROUTING Revision 3.5 * Copyright 2018, Joyent, Inc. - * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -988,7 +988,7 @@ process_hash_dump(void) } static int -process_hash_iter(const psinfo_t *psinfo, const prfdinfo_t *pr, +process_hash_iter(const psinfo_t *psinfo, const prfdinfo_core_t *pr, struct ps_prochandle *Pr) { proc_fdinfo_t *ph; @@ -1089,7 +1089,7 @@ process_hash_iterate(psinfo_t *psinfo) while ((ent = readdir(dirp)) != NULL) { char path[PATH_MAX]; struct stat st; - prfdinfo_t info; + prfdinfo_core_t info; int fd, len; if (!isdigit(ent->d_name[0])) diff --git a/usr/src/cmd/ptools/pfiles/pfiles.c b/usr/src/cmd/ptools/pfiles/pfiles.c index d7142809f7..ad74bb72ae 100644 --- a/usr/src/cmd/ptools/pfiles/pfiles.c +++ b/usr/src/cmd/ptools/pfiles/pfiles.c @@ -25,6 +25,7 @@ */ /* * Copyright (c) 2017 Joyent, Inc. All Rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <stdio.h> @@ -51,28 +52,19 @@ #include <ucred.h> #include <zone.h> -#define copyflock(dst, src) \ - (dst).l_type = (src).l_type; \ - (dst).l_whence = (src).l_whence; \ - (dst).l_start = (src).l_start; \ - (dst).l_len = (src).l_len; \ - (dst).l_sysid = (src).l_sysid; \ - (dst).l_pid = (src).l_pid; - static char *command; static volatile int interrupt; static int Fflag; static boolean_t nflag = B_FALSE; static void intr(int); -static void dofcntl(struct ps_prochandle *, prfdinfo_t *, int, int); -static void dosocket(struct ps_prochandle *, int); -static void dofifo(struct ps_prochandle *, int); -static void dotli(struct ps_prochandle *, int); +static void dofcntl(struct ps_prochandle *, const prfdinfo_t *, int, int); +static void dosocket(struct ps_prochandle *, const prfdinfo_t *); +static void dosocknames(struct ps_prochandle *, const prfdinfo_t *); +static void dofifo(struct ps_prochandle *, const prfdinfo_t *); static void show_files(struct ps_prochandle *); static void show_fileflags(int); -static void show_door(struct ps_prochandle *, int); -static int getflock(struct ps_prochandle *, int, struct flock *); +static void show_door(struct ps_prochandle *, const prfdinfo_t *); int main(int argc, char **argv) @@ -213,11 +205,13 @@ intr(int sig) /* ------ begin specific code ------ */ + static int -show_file(void *data, prfdinfo_t *info) +show_file(void *data, const prfdinfo_t *info) { struct ps_prochandle *Pr = data; char unknown[12]; + const char *path; char *s; mode_t mode; @@ -265,58 +259,41 @@ show_file(void *data, prfdinfo_t *info) (void) printf(" rdev:%u,%u\n", (unsigned)info->pr_rmajor, (unsigned)info->pr_rminor); + path = proc_fdinfo_misc(info, PR_PATHNAME, NULL); + if (!nflag) { dofcntl(Pr, info, (mode & (S_IFMT|S_ENFMT|S_IXGRP)) == (S_IFREG|S_ENFMT), (mode & S_IFMT) == S_IFDOOR); if (Pstate(Pr) != PS_DEAD) { - char *dev = NULL; - - if ((mode & S_IFMT) == S_IFSOCK) - dosocket(Pr, info->pr_fd); - else if ((mode & S_IFMT) == S_IFIFO) - dofifo(Pr, info->pr_fd); - - if ((mode & S_IFMT) == S_IFCHR) { + switch (mode & S_IFMT) { + case S_IFSOCK: + dosocket(Pr, info); + break; + case S_IFIFO: + dofifo(Pr, info); + break; + case S_IFCHR: /* - * There's no elegant way to determine - * if a character device supports TLI, - * so we lame out and just check a - * hardcoded list of known TLI devices. + * This may be a TLI endpoint. If so, it will + * have socket names in the fdinfo and this + * will print them. */ - int i; - const char *tlidevs[] = { - "tcp", "tcp6", "udp", "udp6", NULL - }; - - /* global zone: /devices paths */ - dev = strrchr(info->pr_path, ':'); - /* also check the /dev path for zones */ - if (dev == NULL) - dev = strrchr(info->pr_path, '/'); - if (dev != NULL) { - dev++; /* skip past the `:' or '/' */ - - for (i = 0; tlidevs[i] != NULL; i++) { - if (strcmp(dev, tlidevs[i]) == - 0) { - dotli(Pr, info->pr_fd); - break; - } - } - } + dosocknames(Pr, info); + break; } } - if (info->pr_path[0] != '\0') - (void) printf(" %s\n", info->pr_path); + if (path != NULL) + (void) printf(" %s\n", path); if (info->pr_offset != -1) { (void) printf(" offset:%lld\n", (long long)info->pr_offset); } } + return (0); } @@ -338,35 +315,13 @@ show_files(struct ps_prochandle *Pr) (void) Pfdinfo_iter(Pr, show_file, Pr); } - -static int -getflock(struct ps_prochandle *Pr, int fd, struct flock *flock_native) -{ - int ret; -#ifdef _LP64 - struct flock64_32 flock_target; - - if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) { - copyflock(flock_target, *flock_native); - ret = pr_fcntl(Pr, fd, F_GETLK, &flock_target); - copyflock(*flock_native, flock_target); - return (ret); - } -#endif /* _LP64 */ - ret = pr_fcntl(Pr, fd, F_GETLK, flock_native); - return (ret); -} - /* examine open file with fcntl() */ static void -dofcntl(struct ps_prochandle *Pr, prfdinfo_t *info, int mandatory, int isdoor) +dofcntl(struct ps_prochandle *Pr, const prfdinfo_t *info, int mandatory, + int isdoor) { - struct flock flock; int fileflags; int fdflags; - int fd; - - fd = info->pr_fd; fileflags = info->pr_fileflags; fdflags = info->pr_fdflags; @@ -378,31 +333,27 @@ dofcntl(struct ps_prochandle *Pr, prfdinfo_t *info, int mandatory, int isdoor) if (fdflags != -1 && (fdflags & FD_CLOEXEC)) (void) printf(" FD_CLOEXEC"); if (isdoor && (Pstate(Pr) != PS_DEAD)) - show_door(Pr, fd); + show_door(Pr, info); (void) fputc('\n', stdout); } else if (isdoor && (Pstate(Pr) != PS_DEAD)) { (void) printf(" "); - show_door(Pr, fd); + show_door(Pr, info); (void) fputc('\n', stdout); } - flock.l_type = F_WRLCK; - flock.l_whence = 0; - flock.l_start = 0; - flock.l_len = 0; - flock.l_sysid = 0; - flock.l_pid = 0; - if ((Pstate(Pr) != PS_DEAD) && (getflock(Pr, fd, &flock) != -1)) { - if (flock.l_type != F_UNLCK && (flock.l_sysid || flock.l_pid)) { - unsigned long sysid = flock.l_sysid; - - (void) printf(" %s %s lock set by", + if (Pstate(Pr) != PS_DEAD) { + if (info->pr_locktype != F_UNLCK && + (info->pr_locksysid != -1 || info->pr_lockpid != -1)) { + unsigned long sysid = info->pr_locksysid; + + (void) printf(" %s %s lock set", mandatory ? "mandatory" : "advisory", - flock.l_type == F_RDLCK? "read" : "write"); + info->pr_locktype == F_RDLCK? "read" : "write"); if (sysid) - (void) printf(" system 0x%lX", sysid); - if (flock.l_pid) - (void) printf(" process %d", (int)flock.l_pid); + (void) printf(" by system 0x%lX", sysid); + if (info->pr_lockpid != -1) + (void) printf(" by process %d", + (int)info->pr_lockpid); (void) fputc('\n', stdout); } } @@ -484,11 +435,11 @@ show_peer_process(pid_t ppid) /* show door info */ static void -show_door(struct ps_prochandle *Pr, int fd) +show_door(struct ps_prochandle *Pr, const prfdinfo_t *info) { door_info_t door_info; - if (pr_door_info(Pr, fd, &door_info) != 0) + if (pr_door_info(Pr, info->pr_fd, &door_info) != 0) return; (void) printf(" door to"); @@ -500,7 +451,7 @@ show_door(struct ps_prochandle *Pr, int fd) * needed for AF_UNIX sockets. */ static void -show_sockaddr(const char *str, struct sockaddr *sa, socklen_t len) +show_sockaddr(const char *str, const struct sockaddr *sa, socklen_t len) { struct sockaddr_in *so_in = (struct sockaddr_in *)(void *)sa; struct sockaddr_in6 *so_in6 = (struct sockaddr_in6 *)(void *)sa; @@ -527,11 +478,9 @@ show_sockaddr(const char *str, struct sockaddr *sa, socklen_t len) return; case AF_UNIX: if (len >= sizeof (so_un->sun_family)) { - /* Null terminate */ - len -= sizeof (so_un->sun_family); - so_un->sun_path[len] = '\0'; - (void) printf("\t%s: AF_UNIX %s\n", - str, so_un->sun_path); + (void) printf("\t%s: AF_UNIX %.*s\n", + str, len - sizeof (so_un->sun_family), + so_un->sun_path); } return; case AF_IMPLINK: p = "AF_IMPLINK"; break; @@ -608,74 +557,74 @@ show_socktype(uint_t type) #define BUFSIZE 200 static void -show_sockopts(struct ps_prochandle *Pr, int fd) +show_sockopts(struct ps_prochandle *Pr, const prfdinfo_t *info) { - int val, vlen; + const int *val; + size_t vlen; char buf[BUFSIZE]; char buf1[32]; char ipaddr[INET_ADDRSTRLEN]; int i; - in_addr_t nexthop_val; + const in_addr_t *nexthop_val; + const prsockopts_bool_opts_t *opts; struct boolopt { - int level; int opt; const char *name; }; static struct boolopt boolopts[] = { - { SOL_SOCKET, SO_DEBUG, "SO_DEBUG," }, - { SOL_SOCKET, SO_REUSEADDR, "SO_REUSEADDR," }, - { SOL_SOCKET, SO_KEEPALIVE, "SO_KEEPALIVE," }, - { SOL_SOCKET, SO_DONTROUTE, "SO_DONTROUTE," }, - { SOL_SOCKET, SO_BROADCAST, "SO_BROADCAST," }, - { SOL_SOCKET, SO_OOBINLINE, "SO_OOBINLINE," }, - { SOL_SOCKET, SO_DGRAM_ERRIND, "SO_DGRAM_ERRIND,"}, - { SOL_SOCKET, SO_ALLZONES, "SO_ALLZONES," }, - { SOL_SOCKET, SO_MAC_EXEMPT, "SO_MAC_EXEMPT," }, - { SOL_SOCKET, SO_MAC_IMPLICIT, "SO_MAC_IMPLICIT," }, - { SOL_SOCKET, SO_EXCLBIND, "SO_EXCLBIND," }, - { SOL_SOCKET, SO_VRRP, "SO_VRRP," }, - { IPPROTO_UDP, UDP_NAT_T_ENDPOINT, "UDP_NAT_T_ENDPOINT," }, + { PR_SO_DEBUG, "SO_DEBUG," }, + { PR_SO_REUSEADDR, "SO_REUSEADDR," }, + { PR_SO_KEEPALIVE, "SO_KEEPALIVE," }, + { PR_SO_DONTROUTE, "SO_DONTROUTE," }, + { PR_SO_BROADCAST, "SO_BROADCAST," }, + { PR_SO_OOBINLINE, "SO_OOBINLINE," }, + { PR_SO_DGRAM_ERRIND, "SO_DGRAM_ERRIND,"}, + { PR_SO_ALLZONES, "SO_ALLZONES," }, + { PR_SO_MAC_EXEMPT, "SO_MAC_EXEMPT," }, + { PR_SO_MAC_IMPLICIT, "SO_MAC_IMPLICIT," }, + { PR_SO_EXCLBIND, "SO_EXCLBIND," }, + { PR_SO_VRRP, "SO_VRRP," }, + { PR_UDP_NAT_T_ENDPOINT, "UDP_NAT_T_ENDPOINT," }, }; - struct linger l; + const struct linger *l; + + opts = proc_fdinfo_misc(info, PR_SOCKOPTS_BOOL_OPTS, NULL); buf[0] = '!'; /* sentinel value, never printed */ buf[1] = '\0'; for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]); i++) { - vlen = sizeof (val); - if (pr_getsockopt(Pr, fd, boolopts[i].level, boolopts[i].opt, - &val, &vlen) == 0 && val != 0) + if (opts != NULL && opts->prsock_bool_opts & boolopts[i].opt) (void) strlcat(buf, boolopts[i].name, sizeof (buf)); } - vlen = sizeof (l); - if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_LINGER, &l, &vlen) == 0 && - l.l_onoff != 0) { + l = proc_fdinfo_misc(info, PR_SOCKOPT_LINGER, NULL); + if (l != NULL && l->l_onoff != 0) { (void) snprintf(buf1, sizeof (buf1), "SO_LINGER(%d),", - l.l_linger); + l->l_linger); (void) strlcat(buf, buf1, sizeof (buf)); } - vlen = sizeof (val); - if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_SNDBUF, &val, &vlen) == 0) { - (void) snprintf(buf1, sizeof (buf1), "SO_SNDBUF(%d),", val); + val = proc_fdinfo_misc(info, PR_SOCKOPT_SNDBUF, NULL); + if (val != NULL) { + (void) snprintf(buf1, sizeof (buf1), "SO_SNDBUF(%d),", *val); (void) strlcat(buf, buf1, sizeof (buf)); } - vlen = sizeof (val); - if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_RCVBUF, &val, &vlen) == 0) { - (void) snprintf(buf1, sizeof (buf1), "SO_RCVBUF(%d),", val); + + val = proc_fdinfo_misc(info, PR_SOCKOPT_RCVBUF, NULL); + if (val != NULL) { + (void) snprintf(buf1, sizeof (buf1), "SO_RCVBUF(%d),", *val); (void) strlcat(buf, buf1, sizeof (buf)); } - vlen = sizeof (nexthop_val); - if (pr_getsockopt(Pr, fd, IPPROTO_IP, IP_NEXTHOP, &nexthop_val, - &vlen) == 0) { - if (vlen > 0) { - (void) inet_ntop(AF_INET, (void *) &nexthop_val, - ipaddr, sizeof (ipaddr)); - (void) snprintf(buf1, sizeof (buf1), "IP_NEXTHOP(%s),", - ipaddr); - (void) strlcat(buf, buf1, sizeof (buf)); - } + + + nexthop_val = proc_fdinfo_misc(info, PR_SOCKOPT_IP_NEXTHOP, &vlen); + if (nexthop_val != NULL && vlen > 0) { + (void) inet_ntop(AF_INET, (void *) nexthop_val, + ipaddr, sizeof (ipaddr)); + (void) snprintf(buf1, sizeof (buf1), "IP_NEXTHOP(%s),", + ipaddr); + (void) strlcat(buf, buf1, sizeof (buf)); } buf[strlen(buf) - 1] = '\0'; /* overwrites sentinel if no options */ @@ -685,11 +634,12 @@ show_sockopts(struct ps_prochandle *Pr, int fd) #define MAXNALLOC 32 static void -show_sockfilters(struct ps_prochandle *Pr, int fd) +show_sockfilters(struct ps_prochandle *Pr, const prfdinfo_t *info) { struct fil_info *fi; int i = 0, nalloc = 2, len = nalloc * sizeof (*fi); boolean_t printhdr = B_TRUE; + int fd = info->pr_fd; fi = calloc(nalloc, sizeof (*fi)); if (fi == NULL) { @@ -749,68 +699,50 @@ show_sockfilters(struct ps_prochandle *Pr, int fd) /* print peer credentials for sockets and named pipes */ static void -dopeerucred(struct ps_prochandle *Pr, int fd) +dopeerucred(struct ps_prochandle *Pr, const prfdinfo_t *info) { ucred_t *peercred = NULL; /* allocated by getpeerucred */ - if (pr_getpeerucred(Pr, fd, &peercred) == 0) { + if (pr_getpeerucred(Pr, info->pr_fd, &peercred) == 0) { show_ucred("peer", peercred); ucred_free(peercred); } } -/* the file is a socket */ static void -dosocket(struct ps_prochandle *Pr, int fd) +dosocknames(struct ps_prochandle *Pr, const prfdinfo_t *info) { - /* A buffer large enough for PATH_MAX size AF_UNIX address */ - long buf[(sizeof (short) + PATH_MAX + sizeof (long) - 1) - / sizeof (long)]; - struct sockaddr *sa = (struct sockaddr *)buf; - socklen_t len; - int type, tlen; - - tlen = sizeof (type); - if (pr_getsockopt(Pr, fd, SOL_SOCKET, SO_TYPE, &type, &tlen) == 0) - show_socktype((uint_t)type); - - show_sockopts(Pr, fd); - show_sockfilters(Pr, fd); - - len = sizeof (buf); - if (pr_getsockname(Pr, fd, sa, &len) == 0) - show_sockaddr("sockname", sa, len); + const struct sockaddr *sa; + size_t vlen; - len = sizeof (buf); - if (pr_getpeername(Pr, fd, sa, &len) == 0) - show_sockaddr("peername", sa, len); + sa = proc_fdinfo_misc(info, PR_SOCKETNAME, &vlen); + if (sa != NULL) + show_sockaddr("sockname", sa, vlen); - dopeerucred(Pr, fd); + sa = proc_fdinfo_misc(info, PR_PEERSOCKNAME, &vlen); + if (sa != NULL) + show_sockaddr("peername", sa, vlen); } -/* the file is a fifo (aka "named pipe") */ +/* the file is a socket */ static void -dofifo(struct ps_prochandle *Pr, int fd) +dosocket(struct ps_prochandle *Pr, const prfdinfo_t *info) { - dopeerucred(Pr, fd); + const int *type; + + type = proc_fdinfo_misc(info, PR_SOCKOPT_TYPE, NULL); + if (type != NULL) + show_socktype((uint_t)*type); + + show_sockopts(Pr, info); + show_sockfilters(Pr, info); + dosocknames(Pr, info); + dopeerucred(Pr, info); } -/* the file is a TLI endpoint */ +/* the file is a fifo (aka "named pipe") */ static void -dotli(struct ps_prochandle *Pr, int fd) +dofifo(struct ps_prochandle *Pr, const prfdinfo_t *info) { - struct strcmd strcmd; - - strcmd.sc_len = STRCMDBUFSIZE; - strcmd.sc_timeout = 5; - - strcmd.sc_cmd = TI_GETMYNAME; - if (pr_ioctl(Pr, fd, _I_CMD, &strcmd, sizeof (strcmd)) == 0) - show_sockaddr("sockname", (void *)&strcmd.sc_buf, - (size_t)strcmd.sc_len); - - strcmd.sc_cmd = TI_GETPEERNAME; - if (pr_ioctl(Pr, fd, _I_CMD, &strcmd, sizeof (strcmd)) == 0) - show_sockaddr("peername", (void *)&strcmd.sc_buf, - (size_t)strcmd.sc_len); + dopeerucred(Pr, info); } diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg index 5876b59f1f..20fe3ceb02 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg @@ -23,6 +23,7 @@ # Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2012 DEY Storage Systems, Inc. All rights reserved. # Copyright 2018 Joyent, Inc. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # @ _START_ @@ -468,7 +469,7 @@ @ MSG_CNOTE_DESC_PSINFO_T "desc: (psinfo_t)" @ MSG_CNOTE_DESC_PSTATUS_T "desc: (pstatus_t)" @ MSG_CNOTE_DESC_STRUCT_UTSNAME "desc: (struct utsname)" -@ MSG_CNOTE_DESC_PRFDINFO_T "desc: (prfdinfo_t)" +@ MSG_CNOTE_DESC_PRFDINFO_T "desc: (prfdinfo_core_t)" @ MSG_CNOTE_DESC_PRSECFLAGS_T "desc: (prsecflags_t)" @ MSG_CNOTE_DESC_PRLWPNAME_T "desc: (prlwpname_t)" diff --git a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c index 674972dc22..657ab05605 100644 --- a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c +++ b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c @@ -12,6 +12,7 @@ /* * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -57,6 +58,6 @@ stack_t stack; sysset_t sysset; timestruc_t ts; struct utsname uts; -prfdinfo_t ptfd; +prfdinfo_core_t ptfd; prsecflags_t psf; prlwpname_t psn; diff --git a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c index 522c974fbd..4f3d8b4dac 100644 --- a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c +++ b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c @@ -25,6 +25,7 @@ * * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -568,22 +569,22 @@ gen_utsname(void) static void gen_prfdinfo(void) { - START(prfdinfo, prfdinfo_t); - - SCALAR_FIELD(prfdinfo_t, pr_fd, 0); - SCALAR_FIELD(prfdinfo_t, pr_mode, 0); - SCALAR_FIELD(prfdinfo_t, pr_uid, 0); - SCALAR_FIELD(prfdinfo_t, pr_gid, 0); - SCALAR_FIELD(prfdinfo_t, pr_major, 0); - SCALAR_FIELD(prfdinfo_t, pr_minor, 0); - SCALAR_FIELD(prfdinfo_t, pr_rmajor, 0); - SCALAR_FIELD(prfdinfo_t, pr_rminor, 0); - SCALAR_FIELD(prfdinfo_t, pr_ino, 0); - SCALAR_FIELD(prfdinfo_t, pr_offset, 0); - SCALAR_FIELD(prfdinfo_t, pr_size, 0); - SCALAR_FIELD(prfdinfo_t, pr_fileflags, 0); - SCALAR_FIELD(prfdinfo_t, pr_fdflags, 0); - ARRAY_FIELD(prfdinfo_t, pr_path, 0); + START(prfdinfo, prfdinfo_core_t); + + SCALAR_FIELD(prfdinfo_core_t, pr_fd, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_mode, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_uid, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_gid, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_major, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_minor, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_rmajor, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_rminor, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_ino, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_offset, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_size, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_fileflags, 0); + SCALAR_FIELD(prfdinfo_core_t, pr_fdflags, 0); + ARRAY_FIELD(prfdinfo_core_t, pr_path, 0); END; } diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout.h b/usr/src/cmd/sgs/elfdump/common/struct_layout.h index 022640e906..7c43c33f99 100644 --- a/usr/src/cmd/sgs/elfdump/common/struct_layout.h +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout.h @@ -27,6 +27,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _STRUCT_LAYOUT_H @@ -507,7 +508,7 @@ typedef struct { } sl_utsname_layout_t; /* - * Layout description of prdinfo_t, from <sys/procfs.h>. + * Layout description of prfdinfo_core_t, from <sys/procfs.h>. */ typedef struct { sl_field_t sizeof_struct; diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c index 42260b1e43..f040da7f3d 100644 --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <struct_layout.h> @@ -360,7 +361,7 @@ static const sl_utsname_layout_t utsname_layout = { static const sl_prfdinfo_layout_t prfdinfo_layout = { - { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_core_t) */ { 0, 4, 0, 0 }, /* pr_fd */ { 4, 4, 0, 0 }, /* pr_mode */ { 8, 4, 0, 0 }, /* pr_uid */ diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c index de104e90ec..0e37cc5b95 100644 --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <struct_layout.h> @@ -360,7 +361,7 @@ static const sl_utsname_layout_t utsname_layout = { static const sl_prfdinfo_layout_t prfdinfo_layout = { - { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_core_t) */ { 0, 4, 0, 0 }, /* pr_fd */ { 4, 4, 0, 0 }, /* pr_mode */ { 8, 4, 0, 0 }, /* pr_uid */ diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c index ead0ae6b7b..3e3abf9d2b 100644 --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <struct_layout.h> @@ -360,7 +361,7 @@ static const sl_utsname_layout_t utsname_layout = { static const sl_prfdinfo_layout_t prfdinfo_layout = { - { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_core_t) */ { 0, 4, 0, 0 }, /* pr_fd */ { 4, 4, 0, 0 }, /* pr_mode */ { 8, 4, 0, 0 }, /* pr_uid */ diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c index 00eaae9146..7ca7b27b1d 100644 --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <struct_layout.h> @@ -360,7 +361,7 @@ static const sl_utsname_layout_t utsname_layout = { static const sl_prfdinfo_layout_t prfdinfo_layout = { - { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_core_t) */ { 0, 4, 0, 0 }, /* pr_fd */ { 4, 4, 0, 0 }, /* pr_mode */ { 8, 4, 0, 0 }, /* pr_uid */ diff --git a/usr/src/lib/libproc/Makefile b/usr/src/lib/libproc/Makefile index 1e42afebbb..ad175b0e9d 100644 --- a/usr/src/lib/libproc/Makefile +++ b/usr/src/lib/libproc/Makefile @@ -22,6 +22,7 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # include ../Makefile.lib @@ -34,11 +35,10 @@ clean := TARGET= clean clobber := TARGET= clobber delete := TARGET= delete install := TARGET= install -lint := TARGET= lint _msg := TARGET= _msg package := TARGET= package -LIBRARY= libproc.a +LIBRARY= libproc.a TEXT_DOMAIN= SUNW_OST_OSLIB XGETFLAGS= -a POFILE= $(LIBRARY:.a=.po) @@ -61,7 +61,7 @@ $(ROOTHDRDIR)/%: common/% .KEEP_STATE: -all clean clobber delete install lint package: $(SUBDIRS) +all clean clobber delete install package: $(SUBDIRS) install_h: $(ROOTHDRS) diff --git a/usr/src/lib/libproc/Makefile.com b/usr/src/lib/libproc/Makefile.com index 7ed72f97ed..9bc99f1b40 100644 --- a/usr/src/lib/libproc/Makefile.com +++ b/usr/src/lib/libproc/Makefile.com @@ -24,6 +24,7 @@ # Copyright (c) 2013 by Delphix. All rights reserved. # # Copyright (c) 2018, Joyent, Inc. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. LIBRARY = libproc.a VERS = .1 @@ -70,6 +71,7 @@ CMNOBJS = \ proc_get_info.o \ proc_names.o \ proc_arg.o \ + proc_fd.o \ proc_set.o \ proc_stdio.o @@ -84,13 +86,12 @@ include ../../Makefile.rootfs SRCS = $(CMNOBJS:%.o=../common/%.c) $(ISAOBJS:%.o=%.c) -LIBS = $(DYNLIB) $(LINTLIB) +LIBS = $(DYNLIB) LDLIBS += -lrtld_db -lelf -lctf -lc CSTD = $(CSTD_GNU99) CPPFLAGS += $($(MACH64)_CPPFLAGS) SRCDIR = ../common -$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CFLAGS += $(CCVERBOSE) CPPFLAGS += -I$(SRCDIR) @@ -114,8 +115,6 @@ DYNFLAGS += $(BNODIRECT) $(ZDIRECT) $(ZLAZYLOAD) all: $(LIBS) -lint: lintcheck - # include library targets include ../../Makefile.targ diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c index 9af5026014..5a135aef17 100644 --- a/usr/src/lib/libproc/common/Pcontrol.c +++ b/usr/src/lib/libproc/common/Pcontrol.c @@ -27,6 +27,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2015, Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <assert.h> @@ -1201,6 +1202,7 @@ Pfree(struct ps_prochandle *P) while (P->num_fd > 0) { fd_info_t *fip = list_next(&P->fd_head); list_unlink(fip); + proc_fdinfo_free(fip->fd_info); free(fip); P->num_fd--; } diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h index e05ff8b430..a2a875e145 100644 --- a/usr/src/lib/libproc/common/Pcontrol.h +++ b/usr/src/lib/libproc/common/Pcontrol.h @@ -26,6 +26,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _PCONTROL_H @@ -147,7 +148,7 @@ typedef struct lwp_info { /* per-lwp information from core file */ typedef struct fd_info { plist_t fd_list; /* linked list */ - prfdinfo_t fd_info; /* fd info */ + prfdinfo_t *fd_info; /* fd info */ } fd_info_t; typedef struct core_info { /* information specific to core files */ diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c index dadda5b2a7..0532346922 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -27,6 +27,7 @@ * Copyright (c) 2018, Joyent, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2015 Gary Mills + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <sys/types.h> @@ -50,6 +51,7 @@ #include "Pcontrol.h" #include "P32ton.h" #include "Putil.h" +#include "proc_fd.h" #ifdef __x86 #include "Pcore_linux.h" #endif @@ -754,7 +756,7 @@ err: static int note_fdinfo(struct ps_prochandle *P, size_t nbytes) { - prfdinfo_t prfd; + prfdinfo_core_t prfd; fd_info_t *fip; if ((nbytes < sizeof (prfd)) || @@ -767,7 +769,13 @@ note_fdinfo(struct ps_prochandle *P, size_t nbytes) dprintf("Pgrab_core: failed to add NT_FDINFO\n"); return (-1); } - (void) memcpy(&fip->fd_info, &prfd, sizeof (prfd)); + if (fip->fd_info == NULL) { + if (proc_fdinfo_from_core(&prfd, &fip->fd_info) != 0) { + dprintf("Pgrab_core: failed to convert NT_FDINFO\n"); + return (-1); + } + } + return (0); } diff --git a/usr/src/lib/libproc/common/Pfdinfo.c b/usr/src/lib/libproc/common/Pfdinfo.c index 27264091f8..c822ec8434 100644 --- a/usr/src/lib/libproc/common/Pfdinfo.c +++ b/usr/src/lib/libproc/common/Pfdinfo.c @@ -14,6 +14,7 @@ */ /* * Copyright (c) 2013 Joyent, Inc. All Rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <limits.h> @@ -27,6 +28,7 @@ #include "libproc.h" #include "Pcontrol.h" +#include "proc_fd.h" /* * Pfdinfo.c - obtain open file information. @@ -51,10 +53,13 @@ Pfd2info(struct ps_prochandle *P, int fd) } for (i = 0; i < P->num_fd; i++, fip = list_next(fip)) { - if (fip->fd_info.pr_fd == fd) { + if (fip->fd_info == NULL) + continue; + + if (fip->fd_info->pr_fd == fd) { return (fip); } - if (fip->fd_info.pr_fd < fd) { + if (fip->fd_info->pr_fd < fd) { break; } } @@ -63,12 +68,34 @@ Pfd2info(struct ps_prochandle *P, int fd) if ((fip = calloc(1, sizeof (*fip))) == NULL) return (NULL); - fip->fd_info.pr_fd = fd; list_link(fip, next ? next : (void *)&(P->fd_head)); P->num_fd++; return (fip); } +static int +fdwalk_cb(const prfdinfo_t *info, void *arg) +{ + struct ps_prochandle *P = arg; + fd_info_t *fip; + + fip = Pfd2info(P, info->pr_fd); + if (fip == NULL) { + errno = ENOMEM; + return (-1); + } + + if (fip->fd_info == NULL) + fip->fd_info = proc_fdinfo_dup(info); + + if (fip->fd_info == NULL) { + errno = ENOMEM; + return (-1); + } + + return (0); +} + /* * Attempt to load the open file information from a live process. */ @@ -81,83 +108,13 @@ load_fdinfo(struct ps_prochandle *P) * This is an edge case it isn't worth adding additional state to * to eliminate. */ - if (P->num_fd > 0) { + if (P->num_fd > 0) return; - } - if (P->state != PS_DEAD && P->state != PS_IDLE) { - char dir_name[PATH_MAX]; - char path[PATH_MAX]; - struct dirent *ent; - DIR *dirp; - int fd; - - /* - * Try to get the path information first. - */ - (void) snprintf(dir_name, sizeof (dir_name), - "%s/%d/path", procfs_path, (int)P->pid); - dirp = opendir(dir_name); - if (dirp == NULL) { - return; - } - ent = NULL; - while ((ent = readdir(dirp)) != NULL) { - fd_info_t *fip; - prfdinfo_t *info; - int len; - struct stat64 stat; - - if (!isdigit(ent->d_name[0])) - continue; - - fd = atoi(ent->d_name); - - fip = Pfd2info(P, fd); - info = &fip->fd_info; - info->pr_fd = fd; - - if (pr_fstat64(P, fd, &stat) == 0) { - info->pr_mode = stat.st_mode; - info->pr_uid = stat.st_uid; - info->pr_gid = stat.st_gid; - info->pr_major = major(stat.st_dev); - info->pr_minor = minor(stat.st_dev); - info->pr_rmajor = major(stat.st_rdev); - info->pr_rminor = minor(stat.st_rdev); - info->pr_size = stat.st_size; - info->pr_ino = stat.st_ino; - } - - info->pr_fileflags = pr_fcntl(P, fd, F_GETXFL, 0); - info->pr_fdflags = pr_fcntl(P, fd, F_GETFD, 0); - info->pr_offset = pr_llseek(P, fd, 0, SEEK_CUR); - - /* attempt to determine the path to it */ - switch (info->pr_mode & S_IFMT) { - case S_IFDOOR: - case S_IFSOCK: - /* not applicable */ - len = -1; - break; - default: - (void) snprintf(path, sizeof (path), - "%s/%d/path/%d", procfs_path, (int)P->pid, - fd); - len = readlink(path, info->pr_path, - sizeof (info->pr_path) - 1); - break; - } - - if (len < 0) { - info->pr_path[0] = 0; - } else { - info->pr_path[len] = 0; - } - } - (void) closedir(dirp); + if (P->state == PS_DEAD || P->state == PS_IDLE) + return; - } + proc_fdwalk(P->pid, fdwalk_cb, P); } int @@ -174,7 +131,7 @@ Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd) for (fip = list_prev(&P->fd_head); fip != (void *)&P->fd_head && fip != NULL; fip = list_prev(fip)) { - if ((rv = func(cd, &fip->fd_info)) != 0) + if ((rv = func(cd, fip->fd_info)) != 0) return (rv); } return (0); diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c index 64ef98065b..e4d4437baa 100644 --- a/usr/src/lib/libproc/common/Pgcore.c +++ b/usr/src/lib/libproc/common/Pgcore.c @@ -27,6 +27,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #define _STRUCTURED_PROC 1 @@ -49,6 +50,7 @@ #include "Pcontrol.h" #include "P32ton.h" +#include "proc_fd.h" typedef enum { STR_NONE, @@ -611,12 +613,19 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) } static int -iter_fd(void *data, prfdinfo_t *fdinfo) +iter_fd(void *data, const prfdinfo_t *fdinfo) { fditer_t *iter = data; + prfdinfo_core_t core; + int ret = 0; - if (write_note(iter->fd_fd, NT_FDINFO, fdinfo, - sizeof (*fdinfo), iter->fd_doff) != 0) + if (proc_fdinfo_to_core(fdinfo, &core) != 0) + return (1); + + ret = write_note(iter->fd_fd, NT_FDINFO, &core, + sizeof (core), iter->fd_doff); + + if (ret != 0) return (1); return (0); } diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h index f783026060..cdf789a621 100644 --- a/usr/src/lib/libproc/common/libproc.h +++ b/usr/src/lib/libproc/common/libproc.h @@ -28,7 +28,7 @@ * Copyright 2019 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright 2019, Carlos Neira <cneirabustos@gmail.com> - * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* @@ -469,6 +469,18 @@ extern int proc_walk(proc_walk_f *, void *, int); #define PR_WALK_INCLUDE_SYS 0x80000000 /* include SSYS processes */ /* + * File descriptor iteration. + */ +typedef int proc_fdwalk_f(const prfdinfo_t *, void *); +extern int proc_fdwalk(pid_t, proc_fdwalk_f *, void *); + +/* + * fdinfo iteration. + */ +typedef int proc_fdinfowalk_f(uint_t, const void *, size_t, void *); +extern int proc_fdinfowalk(const prfdinfo_t *, proc_fdinfowalk_f *, void *); + +/* * Determine if an lwp is in a set as returned from proc_arg_xgrab(). */ extern int proc_lwp_in_set(const char *, lwpid_t); @@ -706,6 +718,9 @@ extern void proc_free_priv(prpriv_t *); extern int proc_get_psinfo(pid_t, psinfo_t *); extern int proc_get_status(pid_t, pstatus_t *); extern int proc_get_secflags(pid_t, prsecflags_t **); +extern prfdinfo_t *proc_get_fdinfo(pid_t, int); +extern const void *proc_fdinfo_misc(const prfdinfo_t *, uint_t, size_t *); +extern void proc_fdinfo_free(prfdinfo_t *); /* * Utility functions for debugging tools to convert numeric fault, @@ -774,7 +789,7 @@ extern int proc_finistdio(void); /* * Iterate over all open files. */ -typedef int proc_fdinfo_f(void *, prfdinfo_t *); +typedef int proc_fdinfo_f(void *, const prfdinfo_t *); extern int Pfdinfo_iter(struct ps_prochandle *, proc_fdinfo_f *, void *); #ifdef __cplusplus diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers index 6e5ff2c21a..1da5918393 100644 --- a/usr/src/lib/libproc/common/mapfile-vers +++ b/usr/src/lib/libproc/common/mapfile-vers @@ -24,7 +24,7 @@ # Copyright 2018 Joyent, Inc. # Copyright (c) 2013 by Delphix. All rights reserved. # Copyright (c) 2019 Carlos Neira <cneirabustos@gmail.com> -# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # # @@ -207,6 +207,10 @@ SYMBOL_VERSION SUNWprivate_1.1 { proc_arg_xpsinfo; proc_content2str; proc_dmodelname; + proc_fdinfo_free; + proc_fdinfo_misc; + proc_fdinfowalk; + proc_fdwalk; proc_finistdio; proc_fltname; proc_fltset2str; @@ -214,6 +218,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { proc_free_priv; proc_get_auxv; proc_get_cred; + proc_get_fdinfo; proc_get_priv; proc_get_psinfo; proc_get_secflags; diff --git a/usr/src/lib/libproc/common/proc_fd.c b/usr/src/lib/libproc/common/proc_fd.c new file mode 100644 index 0000000000..e491934c16 --- /dev/null +++ b/usr/src/lib/libproc/common/proc_fd.c @@ -0,0 +1,350 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/sysmacros.h> + +#include <libgen.h> +#include <limits.h> +#include <alloca.h> +#include <unistd.h> +#include <string.h> +#include <strings.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <dirent.h> + +#include "Pcontrol.h" + +/* + * Walk all file descriptors open for a process and call func() for each. + */ +int +proc_fdwalk(pid_t pid, proc_fdwalk_f *func, void *arg) +{ + struct dirent *dirent; + DIR *fddir; + char *dir; + int ret = 0; + + if (asprintf(&dir, "%s/%d/fd", procfs_path, (int)pid) == -1) + return (-1); + + if ((fddir = opendir(dir)) == NULL) { + free(dir); + return (-1); + } + + free(dir); + + while ((dirent = readdir(fddir)) != NULL) { + prfdinfo_t *info; + char *errptr; + int fd; + + if (!isdigit(dirent->d_name[0])) + continue; + + fd = (int)strtol(dirent->d_name, &errptr, 10); + if (errptr != NULL && *errptr != '\0') + continue; + + if ((info = proc_get_fdinfo(pid, fd)) == NULL) + continue; + + ret = func(info, arg); + + free(info); + + if (ret != 0) + break; + } + + (void) closedir(fddir); + return (ret); +} + +int +proc_fdinfowalk(const prfdinfo_t *info, proc_fdinfowalk_f *func, void *arg) +{ + off_t off = offsetof(prfdinfo_t, pr_misc); + int ret = 0; + + for (;;) { + const pr_misc_header_t *misc; + uint_t type; + size_t size; + + misc = (pr_misc_header_t *)((uint8_t *)info + off); + + /* Found terminating record */ + if (misc->pr_misc_size == 0) + break; + + off += misc->pr_misc_size; + + type = misc->pr_misc_type; + size = misc->pr_misc_size - sizeof (pr_misc_header_t); + misc++; + + ret = func(type, misc, size, arg); + + if (ret != 0) + break; + } + + return (ret); +} + +prfdinfo_t * +proc_get_fdinfo(pid_t pid, int fd) +{ + prfdinfo_t *info = NULL; + char *fname; + uint_t retries; + int ifd, err = EIO; + + if (asprintf(&fname, "%s/%d/fdinfo/%d", + procfs_path, (int)pid, fd) == -1) { + return (NULL); + } + + if ((ifd = open(fname, O_RDONLY)) == -1) { + free(fname); + return (NULL); + } + + free(fname); + + /* + * There is a race between stat()-ing the file and reading from + * it where the size may change. To protect against that, we + * walk the returned data to ensure that it is properly + * terminated. If not, increase the buffer size and try again. + */ + + for (retries = 1; retries < 5; retries++) { + struct stat st; + off_t off; + size_t l; + + if (fstat(ifd, &st) == -1) { + err = errno; + break; + } + + st.st_size *= retries; + + if ((info = reallocf(info, st.st_size)) == NULL) { + err = errno; + break; + } + + if ((l = read(ifd, info, st.st_size)) == -1) { + err = errno; + break; + } + + /* Walk the data to check that is properly terminated. */ + + off = offsetof(prfdinfo_t, pr_misc); + + while (off <= l - sizeof (pr_misc_header_t)) { + pr_misc_header_t *misc; + + misc = (pr_misc_header_t *)((uint8_t *)info + off); + + if (misc->pr_misc_size == 0) { + /* Found terminator record */ + (void) close(ifd); + return (info); + } + + /* Next record */ + off += misc->pr_misc_size; + } + } + + (void) close(ifd); + free(info); + + errno = err; + + return (NULL); +} + +typedef struct proc_fdinfo_misc_cbdata { + uint_t type; + const void *data; + size_t len; +} pfm_data_t; + +static int +proc_fdinfo_misc_cb(uint_t type, const void *data, size_t len, void *datap) +{ + pfm_data_t *cb = (pfm_data_t *)datap; + + if (type == cb->type) { + cb->data = data; + cb->len = len; + return (1); + } + return (0); +} + +const void * +proc_fdinfo_misc(const prfdinfo_t *info, uint_t type, size_t *buflen) +{ + pfm_data_t cb; + + cb.data = NULL; + cb.type = type; + + (void) proc_fdinfowalk(info, proc_fdinfo_misc_cb, (void *)&cb); + + if (cb.data != NULL) { + if (buflen != NULL) + *buflen = cb.len; + + return (cb.data); + } + + return (NULL); +} + +static int +proc_fdinfo_dup_cb(uint_t type, const void *data, size_t len, void *datap) +{ + size_t *sz = (size_t *)datap; + + *sz += len + sizeof (pr_misc_header_t); + return (0); +} + + +prfdinfo_t * +proc_fdinfo_dup(const prfdinfo_t *old) +{ + prfdinfo_t *new; + size_t sz = offsetof(prfdinfo_t, pr_misc); + + /* Determine the size of the miscellaneous items */ + (void) proc_fdinfowalk(old, proc_fdinfo_dup_cb, (void *)&sz); + + /* Add the size of the terminator record */ + sz += sizeof (pr_misc_header_t); + + if ((new = calloc(1, sz)) == NULL) + return (NULL); + + bcopy(old, new, sz); + + return (new); +} + +void +proc_fdinfo_free(prfdinfo_t *info) +{ + free(info); +} + +/* + * Convert a prfdinfo_core_t to prfdinfo_t + */ +int +proc_fdinfo_from_core(const prfdinfo_core_t *core, prfdinfo_t **infop) +{ + prfdinfo_t *info; + size_t len, slen = 0; + + len = offsetof(prfdinfo_t, pr_misc) + sizeof (pr_misc_header_t); + if (*core->pr_path != '\0') { + slen = strlen(core->pr_path) + 1; + len += PRFDINFO_ROUNDUP(slen) + sizeof (pr_misc_header_t); + } + + if ((info = calloc(1, len)) == NULL) + return (-1); + + *infop = info; + + info->pr_fd = core->pr_fd; + info->pr_mode = core->pr_mode; + info->pr_uid = core->pr_uid; + info->pr_gid = core->pr_gid; + info->pr_major = core->pr_major; + info->pr_minor = core->pr_minor; + info->pr_rmajor = core->pr_rmajor; + info->pr_rminor = core->pr_rminor; + info->pr_size = core->pr_size; + info->pr_ino = core->pr_ino; + info->pr_fileflags = core->pr_fileflags; + info->pr_fdflags = core->pr_fdflags; + info->pr_offset = core->pr_offset; + + if (slen != 0) { + pr_misc_header_t *misc; + + misc = (pr_misc_header_t *)&info->pr_misc; + + misc->pr_misc_size = sizeof (*misc) + PRFDINFO_ROUNDUP(slen); + misc->pr_misc_type = PR_PATHNAME; + misc++; + bcopy(core->pr_path, misc, slen); + } + + return (0); +} + +/* + * Convert a prfdinfo_t to prfdinfo_core_t + */ +int +proc_fdinfo_to_core(const prfdinfo_t *info, prfdinfo_core_t *core) +{ + const char *path; + size_t pathl; + + bzero(core, sizeof (*core)); + + core->pr_fd = info->pr_fd; + core->pr_mode = info->pr_mode; + core->pr_uid = info->pr_uid; + core->pr_gid = info->pr_gid; + core->pr_major = info->pr_major; + core->pr_minor = info->pr_minor; + core->pr_rmajor = info->pr_rmajor; + core->pr_rminor = info->pr_rminor; + core->pr_size = info->pr_size; + core->pr_ino = info->pr_ino; + core->pr_fileflags = info->pr_fileflags; + core->pr_fdflags = info->pr_fdflags; + core->pr_offset = info->pr_offset; + + path = proc_fdinfo_misc(info, PR_PATHNAME, &pathl); + if (path != NULL) { + /* + * Rather than provide a truncated path in the pr_path field + * just leave it empty if the path will not fit. + */ + if (pathl <= sizeof (core->pr_path) - 1) + bcopy(path, core->pr_path, pathl + 1); + } + + return (0); +} diff --git a/usr/src/lib/libproc/common/proc_fd.h b/usr/src/lib/libproc/common/proc_fd.h new file mode 100644 index 0000000000..0ada83fca7 --- /dev/null +++ b/usr/src/lib/libproc/common/proc_fd.h @@ -0,0 +1,32 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. + */ + +#ifndef _PROC_FD_H +#define _PROC_FD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Private functions */ +extern int proc_fdinfo_from_core(const prfdinfo_core_t *, prfdinfo_t **); +extern int proc_fdinfo_to_core(const prfdinfo_t *, prfdinfo_core_t *); +extern prfdinfo_t *proc_fdinfo_dup(const prfdinfo_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _PROC_FD_H */ diff --git a/usr/src/man/man3lib/libproc.3lib b/usr/src/man/man3lib/libproc.3lib index 94ddc8b558..3b38bda64f 100644 --- a/usr/src/man/man3lib/libproc.3lib +++ b/usr/src/man/man3lib/libproc.3lib @@ -11,7 +11,7 @@ .\" .\" Copyright 2018 Joyent, Inc. .\" Copyright (c) 2019 Carlos Neira <cneirabustos@gmail.com> -.\" Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. .\" .Dd February 22, 2019 .Dt LIBPROC 3LIB @@ -311,7 +311,8 @@ library. .It Sy proc_dmodelname Ta Sy proc_finistdio .It Sy proc_fltname Ta Sy proc_fltset2str .It Sy proc_flushstdio Ta Sy proc_proc_get_auxv -.It Sy proc_get_cred Ta Sy proc_get_priv +.It Sy proc_fdinfo_misc Ta Sy proc_get_cred +.It Sy proc_get_fdinfo Ta Sy proc_get_priv .It Sy proc_get_psinfo Ta Sy proc_get_status .It Sy proc_get_initstdio Ta Sy proc_lwp_in_set .It Sy proc_lwp_range_valid Ta Sy proc_signame @@ -562,25 +563,39 @@ This indicates that the contents are invalid. The .Vt prfdinfo_t structure is used with the -.Fn Pfdinfo_iter -function which describes information about a file descriptor. +.Fn Pfdinfo_iter , +.Fn proc_fdwalk , +.Fn proc_fdinfowalk +and +.Fn proc_get_fdinfo +functions and describes information about a file descriptor. The structure is defined as follows: .Bd -literal typedef struct prfdinfo { - int pr_fd; - mode_t pr_mode; - uid_t pr_uid; - gid_t pr_gid; - major_t pr_major; /* think stat.st_dev */ - minor_t pr_minor; - major_t pr_rmajor; /* think stat.st_rdev */ - minor_t pr_rminor; - ino64_t pr_ino; - off64_t pr_offset; - off64_t pr_size; - int pr_fileflags; /* fcntl(F_GETXFL), etc */ - int pr_fdflags; /* fcntl(F_GETFD), etc. */ - char pr_path[MAXPATHLEN]; + int pr_fd; /* file descriptor number */ + mode_t pr_mode; /* (see st_mode in stat(2)) */ + ino64_t pr_ino; /* inode number */ + off64_t pr_size; /* file size */ + off64_t pr_offset; /* current offset */ + uid_t pr_uid; /* owner's user id */ + gid_t pr_gid; /* owner's group id */ + major_t pr_major; /* major number of device */ + minor_t pr_minor; /* minor number of device */ + major_t pr_rmajor; /* major number (if special file) */ + minor_t pr_rminor; /* minor number (if special file) */ + int pr_fileflags; /* (see F_GETXFL in fcntl(2)) */ + int pr_fdflags; /* (see F_GETFD in fcntl(2)) */ + short pr_locktype; /* (see F_GETLK in fcntl(2)) */ + pid_t pr_lockpid; /* process holding file lock */ + int pr_locksysid; /* sysid of locking process */ + pid_t pr_peerpid; /* peer process (socket, door) */ + int pr_filler[25]; /* reserved for future use */ + char pr_peername[PRFNSZ]; /* peer process name */ +#if __STDC_VERSION__ >= 199901L + uint8_t pr_misc[]; /* self describing structures */ +else + uint8_t pr_misc[1]; /* self describing structures */ +#endif } prfdinfo_t; .Ed .Pp @@ -650,6 +665,31 @@ and .Dv F_GETFD respectively. .Pp +The +.Fa pr_locktype , +.Fa pr_lockpid , +and +.Fa pr_locksysid +contain the information that would have been returned by a call to +.Xr fcntl 2 +with an argument of +.Dv F_GETLK . +.Pp +The +.Fa pr_peerpid +and +.Fa pr_peername +members contain the process ID and name of any peer endpoint of a +connection-oriented socket or stream fd. +This information is the same as that which would be returned by a call to +.Xr getpeerucred 3C +.Pp +The +.Fa pr_misc +member contains miscellaneous additional data relating to the file descriptor. +The format of these data is described in +.Xr proc 4 . +.Pp .Vt prsyminfo_t .Pp The @@ -747,6 +787,54 @@ Both structures are defined in For additional information on using this type, see .Xr Plwp_iter_all 3PROC . .Pp +.Vt proc_fdinfowalk_f +.Pp +The +.Vt proc_fdinfowalk_f +is a function pointer type that is used with the +.Fn proc_fdinfowalk +function to walk the miscellaneous data items contained within a +.Vt prfdinfo_t +structure. +It is defined as +.Sy typedef +.Ft int +.Fo proc_fdinfowalk_f +.Fa "uint_t" +.Fa "const void *" +.Fa "size_t" +.Fa "void *" +.Fc . +The first argument contains the type of the miscellaneous information being +presented, the second and third provide a pointer to the associated data and +the length of that data. +The final argument is a pointer to an argument that the user specifies. +For more information on using this, see +.Xr proc_fdinfowalk 3PROC . +.Pp +.Vt proc_fdwalk_f +.Pp +The +.Vt proc_fdwalk_f +is a function pointer type that is used with the +.Fn proc_fdwalk +function. +It is defined as +.Sy typedef +.Ft int +.Fo proc_fdwalk_f +.Fa "const prfdinfo_t *" +.Fa "void *" +.Fc . +The first argument contains the file descriptor information. +The +.Sy prfdinfo_t +structure is defined in +.Xr proc 4 . +The final argument is a pointer to an argument that the user specifies. +For more information on using this, see +.Xr proc_fdwalk 3PROC . +.Pp .Vt proc_walk_f .Pp The @@ -1227,6 +1315,7 @@ changes may occur which break both source and binary compatibility. .Xr proc_flushstdio 3PROC , .Xr proc_get_auxv 3PROC , .Xr proc_get_cred 3PROC , +.Xr proc_get_fdinfo 3PROC , .Xr proc_get_priv 3PROC , .Xr proc_get_psinfo 3PROC , .Xr proc_get_status 3PROC , @@ -1245,6 +1334,8 @@ changes may occur which break both source and binary compatibility. .Xr proc_sysname 3PROC , .Xr proc_sysset2str 3PROC , .Xr proc_unctrl_psinfo 3PROC , +.Xr proc_fdinfowalk 3PROC , +.Xr proc_fdwalk 3PROC , .Xr proc_walk 3PROC .Pp .Xr Pldt 3PROC , diff --git a/usr/src/man/man3proc/Makefile b/usr/src/man/man3proc/Makefile index 00403a19fa..1986a27ead 100644 --- a/usr/src/man/man3proc/Makefile +++ b/usr/src/man/man3proc/Makefile @@ -14,7 +14,7 @@ # Copyright 2013 Nexenta Systems, Inc. All rights reserved. # Copyright 2018 Joyent, Inc. # Copyright 2019, Carlos Neira <cneirabustos@gmail.com> -# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. include $(SRC)/Makefile.master @@ -123,10 +123,14 @@ MANFILES= \ proc_arg_grab.3proc \ proc_arg_psinfo.3proc \ proc_content2str.3proc \ + proc_fdinfo_misc.3proc \ + proc_fdinfowalk.3proc \ + proc_fdwalk.3proc \ proc_fltname.3proc \ proc_fltset2str.3proc \ proc_get_auxv.3proc \ proc_get_cred.3proc \ + proc_get_fdinfo.3proc \ proc_get_priv.3proc \ proc_get_psinfo.3proc \ proc_get_status.3proc \ @@ -222,6 +226,7 @@ MANLINKS= \ proc_arg_xgrab.3proc \ proc_arg_xpsinfo.3proc \ proc_dmodelname.3proc \ + proc_fdinfo_free.3proc \ proc_finistdio.3proc \ proc_flushstdio.3proc \ proc_free_priv.3proc \ @@ -394,6 +399,8 @@ proc_arg_xpsinfo.3proc := LINKSRC = proc_arg_psinfo.3proc proc_str2content.3proc := LINKSRC = proc_content2str.3proc +proc_fdinfo_free.3proc := LINKSRC = proc_get_fdinfo.3proc + proc_flushstdio.3proc := LINKSRC = proc_initstdio.3proc proc_finistdio.3proc := LINKSRC = proc_initstdio.3proc diff --git a/usr/src/man/man3proc/proc_fdinfo_misc.3proc b/usr/src/man/man3proc/proc_fdinfo_misc.3proc new file mode 100644 index 0000000000..c7cdd4e338 --- /dev/null +++ b/usr/src/man/man3proc/proc_fdinfo_misc.3proc @@ -0,0 +1,71 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +.\" +.Dd January 6, 2020 +.Dt PROC_FDINFO_MISC 3PROC +.Os +.Sh NAME +.Nm proc_fdinfo_misc +.Nd retrieve a miscellaneous information item from a prfdinfo_t structure +.Sh SYNOPSIS +.Lb libproc +.In libproc.h +.Ft const void * +.Fo proc_fdinfo_misc +.Fa "const prfdinfo_t *info" +.Fa "uint_t type" +.Fa "size_t *len" +.Fc +.Sh DESCRIPTION +The +.Fn proc_fdinfo_misc +function is a convenient way to retrieve a miscellaneous information item from +a +.Vt prfdinfo_t +structure. +.Pp +If a miscellaneous item of type +.Fa type +is found, then this function returns a pointer to the data for that item and +updates +.Fa len +with the item's size. +.Pp +In the case that there are multiple instances of the requested type in the +structure, only the first is returned. +To see all instances, use the +.Xr proc_fdinfowalk 3PROC +function. +.Pp +The definition of the +.Vt prfdinfo_t +structure may be found in the +.Sx fdinfo +section of +.Xr proc 4 . +.Sh RETURN VALUES +Upon successful completion, the +.Fn proc_fdinfo_misc +function returns a pointer to the first instance of data with the requested +type. +Otherwise, +.Sy NULL +is returned to indicate that the item was not found. +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr libproc 3LIB , +.Xr proc_fdinfowalk 3PROC , +.Xr proc 4 diff --git a/usr/src/man/man3proc/proc_fdinfowalk.3proc b/usr/src/man/man3proc/proc_fdinfowalk.3proc new file mode 100644 index 0000000000..1a35e9d209 --- /dev/null +++ b/usr/src/man/man3proc/proc_fdinfowalk.3proc @@ -0,0 +1,95 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +.\" +.Dd January 6, 2020 +.Dt PROC_FDINFOWALK 3PROC +.Os +.Sh NAME +.Nm proc_fdinfowalk +.Nd walk the additional miscellaneous information in a prfdinfo_t structure +.Sh SYNOPSIS +.Lb libproc +.In libproc.h +.Ft int +.Fo proc_fdinfowalk +.Fa "const prfdinfo_t *info" +.Fa "proc_fdinfowalk_f *func" +.Fa "void *arg" +.Fc +.Sh DESCRIPTION +The +.Fn proc_fdinfowalk +function walks a +.Vt prfdinfo_t +structure and calls the callback function +.Fa func +once for each miscellaneous item of information present, +along with the user-specified +.Fa arg . +The definition of +.Sy proc_fdinfowalk_f +is available in +.Xr libproc 3LIB . +The miscellaneous data types and structures are found in the +.Sx fdinfo +section of +.Xr proc 4 . +.Pp +.Fa func +will be called once for each miscellaneous item, providing the item's +.Fa type , +.Fa size +and +.Fa address. +The +.Fa size +may include trailing padding bytes which will be set to zero. +.Pp +The return value of the caller's +.Fa func +function determines whether or not iteration will continue. +If +.Fa func +returns a non-zero value, then iteration will terminate and that +return value will be returned to the caller. +To distinguish between system errors and caller errors, it is recommended that +the function only return positive integers in the event of an error. +.Sh RETURN VALUES +Upon successful completion, the +.Fn proc_fdinfowalk +function returns +.Sy 0 . +Otherwise, +.Sy -1 +is returned and +.Sy errno +is updated to reflect the error that occurred. +.Sh ERRORS +In addition to the errors listed below, the +.Fn proc_fdinfowalk +function may fail for the same reasons as the +.Xr opendir 3C , +.Xr readdir 3C , +and +.Xr malloc 3C +functions. +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr malloc 3C , +.Xr opendir 3C , +.Xr readdir 3C , +.Xr libproc 3LIB , +.Xr proc 4 diff --git a/usr/src/man/man3proc/proc_fdwalk.3proc b/usr/src/man/man3proc/proc_fdwalk.3proc new file mode 100644 index 0000000000..52bf29ed60 --- /dev/null +++ b/usr/src/man/man3proc/proc_fdwalk.3proc @@ -0,0 +1,87 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +.\" +.Dd January 6, 2020 +.Dt PROC_FDWALK 3PROC +.Os +.Sh NAME +.Nm proc_fdwalk +.Nd walk the open file descriptors for a process +.Sh SYNOPSIS +.Lb libproc +.In libproc.h +.Ft int +.Fo proc_fdwalk +.Fa "pid_t pid" +.Fa "proc_fdwalk_f *func" +.Fa "void *arg" +.Fc +.Sh DESCRIPTION +The +.Fn proc_fdwalk +function walks all file descriptors currently open in the process with ID +.Fa pid +and calls the callback function +.Fa func +once for each file descriptor with the user-specified +.Fa arg . +The definition of +.Vt proc_fdwalk_f +is available in +.Xr libproc 3LIB . +.Pp +.Fa func +will be called once for each file descriptor and will have its first +argument filled in with the contents of the corresponding +.Pa /proc +.Sy fdinfo +file for the file descriptor. +.Pp +The return value of the caller's +.Fa func +function determines whether or not iteration will continue. +If +.Fa func +returns a non-zero value, then iteration will terminate and that +return value will be returned to the caller. +To distinguish between system errors and caller errors, it is recommended that +the function only return positive integers in the event of an error. +.Sh RETURN VALUES +Upon successful completion, the +.Fn proc_fdwalk +function returns +.Sy 0 . +Otherwise, +.Sy -1 +is returned and +.Sy errno +is updated to reflect the error that occurred. +.Sh ERRORS +In addition to the errors listed below, the +.Fn proc_fdwalk +function may fail for the same reasons as the +.Xr opendir 3C , +.Xr readdir 3C , +and +.Xr malloc 3C +functions. +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr malloc 3C , +.Xr opendir 3C , +.Xr readdir 3C , +.Xr libproc 3LIB , +.Xr proc 4 diff --git a/usr/src/man/man3proc/proc_get_fdinfo.3proc b/usr/src/man/man3proc/proc_get_fdinfo.3proc new file mode 100644 index 0000000000..b85eef16f9 --- /dev/null +++ b/usr/src/man/man3proc/proc_get_fdinfo.3proc @@ -0,0 +1,99 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +.\" +.Dd January 6, 2020 +.Dt PROC_GET_FDINFO 3PROC +.Os +.Sh NAME +.Nm proc_get_fdinfo , +.Nm proc_fdinfo_free +.Nd get process file descriptor information +.Sh LIBRARY +.Lb libproc +.Sh SYNOPSIS +.In libproc.h +.Ft prfdinfo_t * +.Fo proc_get_fdinfo +.Fa "pid_t pid" +.Fa "int fd" +.Fc +.Ft "void" +.Fo proc_fdinfo_free +.Fa "prfdinfo_t *info" +.Fc +.Sh DESCRIPTION +The +.Fn proc_get_fdinfo +function is a convenient way to read the +.Pa /proc/pid/fdinfo/fd +file for the process +.Fa pid +and file descriptor +.Fa fd . +On success, the return value of the function is a pointer to a properly +terminated +.Sy prfdinfo_t +structure. +.Pp +The definition of the +.Vt prfdinfo_t +structure may be found in +.Xr proc 4 . +.Pp +The caller must free the returned memory by calling the +.Fn proc_fdinfo_free +function. +.Pp +The +.Fn proc_fdinfo_free +frees all memory associated with the +.Vt prfdinfo_t +structure passed as +.Fa info . +.Sh RETURN VALUES +Upon successful completion, the +.Fn proc_get_fdinfo +function returns a pointer to an allocated +.Vt prfdinfo_t +structure. +Otherwise, +.Dv NULL +is returned to indicate an error occurred and +.Vt errno +is set to indicate the error. +.Sh ERRORS +In addition to the errors listed below, the +.Fn proc_get_fdinfo +function may fail for the same reasons as the +.Xr fstat 2 , +.Xr malloc 3C , +.Xr open 2 , +and +.Xr read 2 +functions. +The +.Fn proc_get_fdinfo +function will fail if: +.Bl -tag -width Er +.It Er EIO +The data read from the file under +.Pa /proc +is not properly terminated. +.El +.Sh INTERFACE STABILITY +.Sy Uncommitted +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr libproc 3LIB , +.Xr proc 4 diff --git a/usr/src/man/man4/core.4 b/usr/src/man/man4/core.4 index 9c06bcc42e..a718f93159 100644 --- a/usr/src/man/man4/core.4 +++ b/usr/src/man/man4/core.4 @@ -2,15 +2,15 @@ .\" Copyright (C) 2008, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 2012 DEY Storage Systems, Inc. All rights reserved. .\" Copyright (c) 2013, Joyent, Inc. All rights reserved. +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. .\" Copyright 1989 AT&T .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CORE 4 "Jun 6, 2016" +.TH CORE 4 "Jan 6, 2020" .SH NAME core \- process core file .SH DESCRIPTION -.LP The operating system writes out a core file for a process when the process is terminated due to receiving certain signals. A core file is a disk copy of the contents of the process address space at the time the process received the @@ -335,12 +335,12 @@ with the numerical ID returned by \fBgetzoneid\fR(3C). .sp .ne 2 .na -\fB\fBprfdinfo_t\fR\fR +\fB\fBprfdinfo_core_t\fR\fR .ad .RS 20n \fBn_type\fR: \fBNT_FDINFO\fR. This structure contains information about any open file descriptors, including the path, flags, and -\fBstat\fR(2) information. The \fBprfdinfo_t\fR structure is defined in +\fBstat\fR(2) information. The \fBprfdinfo_core_t\fR structure is defined in <\fBsys/procfs.h\fR>. .RE @@ -472,7 +472,6 @@ with the corresponding load object. The size of the core file created by a process can be controlled by the user (see \fBgetrlimit\fR(2)). .SH SEE ALSO -.LP \fBelfdump\fR(1), \fBgcore\fR(1), \fBmdb\fR(1), \fBproc\fR(1), \fBps\fR(1), \fBcoreadm\fR(1M), \fBgetrlimit\fR(2), \fBsetrlimit\fR(2), \fBsetuid\fR(2), \fBsysinfo\fR(2), \fBuname\fR(2), \fBgetzonenamebyid\fR(3C), diff --git a/usr/src/man/man4/proc.4 b/usr/src/man/man4/proc.4 index 81b3e76c67..b53db24537 100644 --- a/usr/src/man/man4/proc.4 +++ b/usr/src/man/man4/proc.4 @@ -1,6 +1,7 @@ .\" Copyright 1989 AT&T .\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 2019, Joyent, Inc. +.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association. .\" .\" The contents of this file are subject to the terms of the .\" Common Development and Distribution License (the "License"). @@ -17,7 +18,7 @@ .\" fields enclosed by brackets "[]" replaced with your own identifying .\" information: Portions Copyright [yyyy] [name of copyright owner] .\" -.Dd January 11, 2019 +.Dd January 6, 2020 .Dt PROC 4 .Os .Sh NAME @@ -1382,6 +1383,140 @@ as .Pa /proc/ Ns Em pid Ns Pa /cwd . An attempt to open any other type of entry fails with .Er EACCES . +.Ss fdinfo +A directory containing information about each of the process's open files. +Each entry is a decimal number corresponding to an open file descriptor in the +process. +Each file contains a +.Sy prfdinfo_t +structure defined as follows: +.Bd -literal -offset 2 +typedef struct prfdinfo { + int pr_fd; /* file descriptor number */ + mode_t pr_mode; /* (see st_mode in stat(2)) */ + uint64_t pr_ino; /* inode number */ + uint64_t pr_size; /* file size */ + int64_t pr_offset; /* current offset of file descriptor */ + uid_t pr_uid; /* owner's user id */ + gid_t pr_gid; /* owner's group id */ + major_t pr_major; /* major number of device containing file */ + minor_t pr_minor; /* minor number of device containing file */ + major_t pr_rmajor; /* major number (if special file) */ + minor_t pr_rminor; /* minor number (if special file) */ + int pr_fileflags; /* (see F_GETXFL in fcntl(2)) */ + int pr_fdflags; /* (see F_GETFD in fcntl(2)) */ + short pr_locktype; /* (see F_GETLK in fcntl(2)) */ + pid_t pr_lockpid; /* process holding file lock (see F_GETLK) */ + int pr_locksysid; /* sysid of locking process (see F_GETLK) */ + pid_t pr_peerpid; /* peer process (socket, door) */ + int pr_filler[25]; /* reserved for future use */ + char pr_peername[PRFNSZ]; /* peer process name */ +#if __STDC_VERSION__ >= 199901L + char pr_misc[]; /* self describing structures */ +#else + char pr_misc[1]; +#endif +} prfdinfo_t; +.Ed +.Pp +The +.Sy pr_misc +element points to a list of additional miscellaneous data items, each of which +has a header of type +.Sy pr_misc_header_t +specifying the size and type, and some data which immediately follow +the header. +.Bd -literal -offset 2 +typedef struct pr_misc_header { + uint_t pr_misc_size; + uint_t pr_misc_type; +} pr_misc_header_t; +.Ed +.Pp +The +.Sy pr_misc_size +field is the sum of the sizes of the header and the associated data and any +trailing padding bytes which will be set to zero. +The end of the list is indicated by a header with a zero size and a type with +all bits set. +.Pp +The following miscellaneous data types can be present: +.Bl -tag -width "PR_SOCKOPT_TCP_CONGESTION" -offset left +.It Sy PR_PATHNAME +The file descriptor's path in the filesystem. +This is a NUL-terminated sequence of characters. +.It Sy PR_SOCKETNAME +A +.Sy sockaddr +structure representing the local socket name for this file descriptor, as +would be returned by calling +.Fn getsockname +within the process. +.It Sy PR_PEERSOCKNAME +A +.Sy sockaddr +structure representing the peer socket name for this file descriptor, as +would be returned by calling +.Fn getpeername +within the process. +.It Sy PR_SOCKOPTS_BOOL_OPTS +An unsigned integer which has bits set corresponding to options which are +set on the underlying socket. +The following bits may be set: +.Bl -tag -width "PR_SO_PASSIVE_CONNECT" +.It Sy PR_SO_DEBUG +.It Sy PR_SO_REUSEADDR +.It Sy PR_SO_REUSEPORT +.It Sy PR_SO_KEEPALIVE +.It Sy PR_SO_DONTROUTE +.It Sy PR_SO_BROADCAST +.It Sy PR_SO_OOBINLINE +.It Sy PR_SO_DGRAM_ERRIND +.It Sy PR_SO_ALLZONES +.It Sy PR_SO_MAC_EXEMPT +.It Sy PR_SO_EXCLBIND +.It Sy PR_SO_PASSIVE_CONNECT +.It Sy PR_SO_ACCEPTCONN +.It Sy PR_UDP_NAT_T_ENDPOINT +.It Sy PR_SO_VRRP +.It Sy PR_SO_MAC_IMPLICIT +.El +.It Sy PR_SOCKOPT_LINGER +A +.Sy struct linger +as would be returned by calling +.Fn getsockopt SO_LINGER +within the process. +.It Sy PR_SOCKOPT_SNDBUF +The data that would be returned by calling +.Fn getsockopt SO_SNDBUF +within the process. +.It Sy PR_SOCKOPT_RCVBUF +The data that would be returned by calling +.Fn getsockopt SO_RCVBUF +within the process. +.It Sy PR_SOCKOPT_IP_NEXTHOP +The data that would be returned by calling +.Fn getsockopt IPPROTO_IP IP_NEXTHOP +within the process. +.It Sy PR_SOCKOPT_IPV6_NEXTHOP +The data that would be returned by calling +.Fn getsockopt IPPROTO_IPV6 IPV6_NEXTHOP +within the process. +.It Sy PR_SOCKOPT_TYPE +The data that would be returned by calling +.Fn getsockopt SO_TYPE +within the process. +.It Sy PR_SOCKOPT_TCP_CONGESTION +For TCP sockets, the data that would be returned by calling +.Fn getsockopt IPPROTO_TCP TCP_CONGESTION +within the process. +This is a NUL-terminated character array containing the name of the congestion +algorithm in use for the socket. +.It Sy PR_SOCKFILTERS_PRIV +Private data relating to up to the first 32 socket filters pushed on this +descriptor. +.El .Ss object A directory containing read-only files with names corresponding to the .Sy pr_mapname diff --git a/usr/src/pkg/manifests/system-library.man3proc.inc b/usr/src/pkg/manifests/system-library.man3proc.inc index 0119a81518..c8509f5273 100644 --- a/usr/src/pkg/manifests/system-library.man3proc.inc +++ b/usr/src/pkg/manifests/system-library.man3proc.inc @@ -12,37 +12,13 @@ # # Copyright 2018 Joyent, Inc. # Copyright (c) 2019 Carlos Neira <cneirabustos@gmail.com> -# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # -file path=usr/share/man/man3proc/proc_service.3proc -file path=usr/share/man/man3proc/ps_lgetregs.3proc -file path=usr/share/man/man3proc/ps_pglobal_lookup.3proc -file path=usr/share/man/man3proc/ps_pread.3proc -file path=usr/share/man/man3proc/ps_pstop.3proc -link path=usr/share/man/man3proc/ps_kill.3proc target=ps_pstop.3proc -link path=usr/share/man/man3proc/ps_lcontinue.3proc target=ps_pstop.3proc -link path=usr/share/man/man3proc/ps_lgetfpregs.3proc target=ps_lgetregs.3proc -link path=usr/share/man/man3proc/ps_lgetxregs.3proc target=ps_lgetregs.3proc -link path=usr/share/man/man3proc/ps_lgetxregsize.3proc \ - target=ps_lgetregs.3proc -link path=usr/share/man/man3proc/ps_lrolltoaddr.3proc target=ps_pstop.3proc -link path=usr/share/man/man3proc/ps_lsetfpregs.3proc target=ps_lgetregs.3proc -link path=usr/share/man/man3proc/ps_lsetregs.3proc target=ps_lgetregs.3proc -link path=usr/share/man/man3proc/ps_lsetxregs.3proc target=ps_lgetregs.3proc -link path=usr/share/man/man3proc/ps_lstop.3proc target=ps_pstop.3proc -link path=usr/share/man/man3proc/ps_pcontinue.3proc target=ps_pstop.3proc -link path=usr/share/man/man3proc/ps_pdread.3proc target=ps_pread.3proc -link path=usr/share/man/man3proc/ps_pdwrite.3proc target=ps_pread.3proc -link path=usr/share/man/man3proc/ps_pglobal_sym.3proc \ - target=ps_pglobal_lookup.3proc -link path=usr/share/man/man3proc/ps_ptread.3proc target=ps_pread.3proc -link path=usr/share/man/man3proc/ps_ptwrite.3proc target=ps_pread.3proc -link path=usr/share/man/man3proc/ps_pwrite.3proc target=ps_pread.3proc file path=usr/share/man/man3proc/Lctlfd.3proc file path=usr/share/man/man3proc/Lfree.3proc -file path=usr/share/man/man3proc/Lgrab_error.3proc file path=usr/share/man/man3proc/Lgrab.3proc +file path=usr/share/man/man3proc/Lgrab_error.3proc file path=usr/share/man/man3proc/Lprochandle.3proc file path=usr/share/man/man3proc/Lpsinfo.3proc file path=usr/share/man/man3proc/Lstate.3proc @@ -54,9 +30,9 @@ file path=usr/share/man/man3proc/Pasfd.3proc file path=usr/share/man/man3proc/Pclearfault.3proc file path=usr/share/man/man3proc/Pclearsig.3proc file path=usr/share/man/man3proc/Pcontent.3proc +file path=usr/share/man/man3proc/Pcreate.3proc file path=usr/share/man/man3proc/Pcreate_agent.3proc file path=usr/share/man/man3proc/Pcreate_error.3proc -file path=usr/share/man/man3proc/Pcreate.3proc file path=usr/share/man/man3proc/Pcred.3proc file path=usr/share/man/man3proc/Pctlfd.3proc file path=usr/share/man/man3proc/Pdelbkpt.3proc @@ -72,10 +48,10 @@ file path=usr/share/man/man3proc/Pgetareg.3proc file path=usr/share/man/man3proc/Pgetauxval.3proc file path=usr/share/man/man3proc/Pgetauxvec.3proc file path=usr/share/man/man3proc/Pgetenv.3proc +file path=usr/share/man/man3proc/Pgrab.3proc file path=usr/share/man/man3proc/Pgrab_core.3proc file path=usr/share/man/man3proc/Pgrab_error.3proc file path=usr/share/man/man3proc/Pgrab_file.3proc -file path=usr/share/man/man3proc/Pgrab.3proc file path=usr/share/man/man3proc/Pisprocdir.3proc file path=usr/share/man/man3proc/Pissyscall.3proc file path=usr/share/man/man3proc/Pldt.3proc @@ -96,6 +72,36 @@ file path=usr/share/man/man3proc/Pplatform.3proc file path=usr/share/man/man3proc/Ppltdest.3proc file path=usr/share/man/man3proc/Ppriv.3proc file path=usr/share/man/man3proc/Ppsinfo.3proc +file path=usr/share/man/man3proc/Prd_agent.3proc +file path=usr/share/man/man3proc/Pread.3proc +file path=usr/share/man/man3proc/Prelease.3proc +file path=usr/share/man/man3proc/Preopen.3proc +file path=usr/share/man/man3proc/Preset_maps.3proc +file path=usr/share/man/man3proc/Psecflags.3proc +file path=usr/share/man/man3proc/Psetbkpt.3proc +file path=usr/share/man/man3proc/Psetcred.3proc +file path=usr/share/man/man3proc/Psetfault.3proc +file path=usr/share/man/man3proc/Psetflags.3proc +file path=usr/share/man/man3proc/Psetpriv.3proc +file path=usr/share/man/man3proc/Psetrun.3proc +file path=usr/share/man/man3proc/Psetsignal.3proc +file path=usr/share/man/man3proc/Psetsysentry.3proc +file path=usr/share/man/man3proc/Psetwapt.3proc +file path=usr/share/man/man3proc/Psetzoneid.3proc +file path=usr/share/man/man3proc/Psignal.3proc +file path=usr/share/man/man3proc/Pstack_iter.3proc +file path=usr/share/man/man3proc/Pstate.3proc +file path=usr/share/man/man3proc/Pstatus.3proc +file path=usr/share/man/man3proc/Pstopstatus.3proc +file path=usr/share/man/man3proc/Psymbol_iter.3proc +file path=usr/share/man/man3proc/Psync.3proc +file path=usr/share/man/man3proc/Psysentry.3proc +file path=usr/share/man/man3proc/Puname.3proc +file path=usr/share/man/man3proc/Pupdate_maps.3proc +file path=usr/share/man/man3proc/Pupdate_syms.3proc +file path=usr/share/man/man3proc/Pwrite.3proc +file path=usr/share/man/man3proc/Pxecbkpt.3proc +file path=usr/share/man/man3proc/Pzonename.3proc file path=usr/share/man/man3proc/pr_access.3proc file path=usr/share/man/man3proc/pr_close.3proc file path=usr/share/man/man3proc/pr_creat.3proc @@ -133,52 +139,31 @@ file path=usr/share/man/man3proc/pr_stat.3proc file path=usr/share/man/man3proc/pr_statvfs.3proc file path=usr/share/man/man3proc/pr_unlink.3proc file path=usr/share/man/man3proc/pr_waitid.3proc -file path=usr/share/man/man3proc/Prd_agent.3proc -file path=usr/share/man/man3proc/Pread.3proc -file path=usr/share/man/man3proc/Prelease.3proc -file path=usr/share/man/man3proc/Preopen.3proc -file path=usr/share/man/man3proc/Preset_maps.3proc file path=usr/share/man/man3proc/proc_arg_grab.3proc file path=usr/share/man/man3proc/proc_arg_psinfo.3proc file path=usr/share/man/man3proc/proc_content2str.3proc +file path=usr/share/man/man3proc/proc_fdinfo_misc.3proc +file path=usr/share/man/man3proc/proc_fdinfowalk.3proc +file path=usr/share/man/man3proc/proc_fdwalk.3proc file path=usr/share/man/man3proc/proc_fltname.3proc file path=usr/share/man/man3proc/proc_fltset2str.3proc file path=usr/share/man/man3proc/proc_get_auxv.3proc file path=usr/share/man/man3proc/proc_get_cred.3proc +file path=usr/share/man/man3proc/proc_get_fdinfo.3proc file path=usr/share/man/man3proc/proc_get_priv.3proc file path=usr/share/man/man3proc/proc_get_psinfo.3proc file path=usr/share/man/man3proc/proc_get_status.3proc file path=usr/share/man/man3proc/proc_initstdio.3proc file path=usr/share/man/man3proc/proc_lwp_in_set.3proc +file path=usr/share/man/man3proc/proc_service.3proc file path=usr/share/man/man3proc/proc_str2flt.3proc file path=usr/share/man/man3proc/proc_str2fltset.3proc file path=usr/share/man/man3proc/proc_unctrl_psinfo.3proc file path=usr/share/man/man3proc/proc_walk.3proc -file path=usr/share/man/man3proc/Psecflags.3proc -file path=usr/share/man/man3proc/Psetbkpt.3proc -file path=usr/share/man/man3proc/Psetcred.3proc -file path=usr/share/man/man3proc/Psetfault.3proc -file path=usr/share/man/man3proc/Psetflags.3proc -file path=usr/share/man/man3proc/Psetpriv.3proc -file path=usr/share/man/man3proc/Psetrun.3proc -file path=usr/share/man/man3proc/Psetsignal.3proc -file path=usr/share/man/man3proc/Psetsysentry.3proc -file path=usr/share/man/man3proc/Psetwapt.3proc -file path=usr/share/man/man3proc/Psetzoneid.3proc -file path=usr/share/man/man3proc/Psignal.3proc -file path=usr/share/man/man3proc/Pstack_iter.3proc -file path=usr/share/man/man3proc/Pstate.3proc -file path=usr/share/man/man3proc/Pstatus.3proc -file path=usr/share/man/man3proc/Pstopstatus.3proc -file path=usr/share/man/man3proc/Psymbol_iter.3proc -file path=usr/share/man/man3proc/Psync.3proc -file path=usr/share/man/man3proc/Psysentry.3proc -file path=usr/share/man/man3proc/Puname.3proc -file path=usr/share/man/man3proc/Pupdate_maps.3proc -file path=usr/share/man/man3proc/Pupdate_syms.3proc -file path=usr/share/man/man3proc/Pwrite.3proc -file path=usr/share/man/man3proc/Pxecbkpt.3proc -file path=usr/share/man/man3proc/Pzonename.3proc +file path=usr/share/man/man3proc/ps_lgetregs.3proc +file path=usr/share/man/man3proc/ps_pglobal_lookup.3proc +file path=usr/share/man/man3proc/ps_pread.3proc +file path=usr/share/man/man3proc/ps_pstop.3proc link path=usr/share/man/man3proc/Lalt_stack.3proc target=Plwp_stack.3proc link path=usr/share/man/man3proc/Lclearfault.3proc target=Pclearfault.3proc link path=usr/share/man/man3proc/Lclearsig.3proc target=Pclearsig.3proc @@ -193,7 +178,8 @@ link path=usr/share/man/man3proc/Lsync.3proc target=Psync.3proc link path=usr/share/man/man3proc/Lwait.3proc target=Pstopstatus.3proc link path=usr/share/man/man3proc/Lxecbkpt.3proc target=Pxecbkpt.3proc link path=usr/share/man/man3proc/Lxecwapt.3proc target=Pxecbkpt.3proc -link path=usr/share/man/man3proc/Paddr_to_text_map.3proc target=Paddr_to_map.3proc +link path=usr/share/man/man3proc/Paddr_to_text_map.3proc \ + target=Paddr_to_map.3proc link path=usr/share/man/man3proc/Pcreate_callback.3proc target=Pcreate.3proc link path=usr/share/man/man3proc/Pdstop.3proc target=Pstopstatus.3proc link path=usr/share/man/man3proc/Pfgcore.3proc target=Pgcore.3proc @@ -201,64 +187,113 @@ link path=usr/share/man/man3proc/Pfgrab_core.3proc target=Pgrab_core.3proc link path=usr/share/man/man3proc/Pfree.3proc target=Prelease.3proc link path=usr/share/man/man3proc/Pissyscall_prev.3proc target=Pissyscall.3proc link path=usr/share/man/man3proc/Plmid_to_ctf.3proc target=Paddr_to_ctf.3proc -link path=usr/share/man/man3proc/Plmid_to_loadobj.3proc target=Paddr_to_loadobj.3proc +link path=usr/share/man/man3proc/Plmid_to_loadobj.3proc \ + target=Paddr_to_loadobj.3proc link path=usr/share/man/man3proc/Plmid_to_map.3proc target=Paddr_to_map.3proc -link path=usr/share/man/man3proc/Plookup_by_name.3proc target=Plookup_by_addr.3proc +link path=usr/share/man/man3proc/Plookup_by_name.3proc \ + target=Plookup_by_addr.3proc link path=usr/share/man/man3proc/Plwp_alt_stack.3proc target=Plwp_stack.3proc -link path=usr/share/man/man3proc/Plwp_getfpregs.3proc target=Plwp_getregs.3proc +link path=usr/share/man/man3proc/Plwp_getfpregs.3proc \ + target=Plwp_getregs.3proc link path=usr/share/man/man3proc/Plwp_iter_all.3proc target=Plwp_iter.3proc link path=usr/share/man/man3proc/Plwp_main_stack.3proc target=Plwp_stack.3proc link path=usr/share/man/man3proc/Plwp_setasrs.3proc target=Plwp_getasrs.3proc -link path=usr/share/man/man3proc/Plwp_setfpregs.3proc target=Plwp_getregs.3proc +link path=usr/share/man/man3proc/Plwp_setfpregs.3proc \ + target=Plwp_getregs.3proc link path=usr/share/man/man3proc/Plwp_setregs.3proc target=Plwp_getregs.3proc -link path=usr/share/man/man3proc/Plwp_setxregs.3proc target=Plwp_getxregs.3proc -link path=usr/share/man/man3proc/Pmapping_iter_resolved.3proc target=Pmapping_iter.3proc +link path=usr/share/man/man3proc/Plwp_setxregs.3proc \ + target=Plwp_getxregs.3proc +link path=usr/share/man/man3proc/Pmapping_iter_resolved.3proc \ + target=Pmapping_iter.3proc link path=usr/share/man/man3proc/Pname_to_ctf.3proc target=Paddr_to_ctf.3proc -link path=usr/share/man/man3proc/Pname_to_loadobj.3proc target=Paddr_to_loadobj.3proc +link path=usr/share/man/man3proc/Pname_to_loadobj.3proc \ + target=Paddr_to_loadobj.3proc link path=usr/share/man/man3proc/Pname_to_map.3proc target=Paddr_to_map.3proc -link path=usr/share/man/man3proc/Pobject_iter_resolved.3proc target=Pmapping_iter.3proc link path=usr/share/man/man3proc/Pobject_iter.3proc target=Pmapping_iter.3proc +link path=usr/share/man/man3proc/Pobject_iter_resolved.3proc \ + target=Pmapping_iter.3proc link path=usr/share/man/man3proc/Pobjname_resolved.3proc target=Pobjname.3proc link path=usr/share/man/man3proc/Ppriv_free.3proc target=Ppriv.3proc link path=usr/share/man/man3proc/Pputareg.3proc target=Pgetareg.3proc -link path=usr/share/man/man3proc/pr_fstat.3proc target=pr_stat.3proc -link path=usr/share/man/man3proc/pr_fstat64.3proc target=pr_stat.3proc -link path=usr/share/man/man3proc/pr_getrlimit64.3proc target=pr_getrlimit.3proc -link path=usr/share/man/man3proc/pr_lstat.3proc target=pr_stat.3proc -link path=usr/share/man/man3proc/pr_lstat64.3proc target=pr_stat.3proc -link path=usr/share/man/man3proc/pr_setrlimit64.3proc target=pr_setrlimit.3proc -link path=usr/share/man/man3proc/pr_stat64.3proc target=pr_stat.3proc link path=usr/share/man/man3proc/Pread_string.3proc target=Pread.3proc -link path=usr/share/man/man3proc/proc_arg_xgrab.3proc target=proc_arg_grab.3proc -link path=usr/share/man/man3proc/proc_arg_xpsinfo.3proc target=proc_arg_psinfo.3proc -link path=usr/share/man/man3proc/proc_dmodelname.3proc target=proc_fltname.3proc -link path=usr/share/man/man3proc/proc_finistdio.3proc target=proc_initstdio.3proc -link path=usr/share/man/man3proc/proc_flushstdio.3proc target=proc_initstdio.3proc -link path=usr/share/man/man3proc/proc_free_priv.3proc target=proc_get_priv.3proc -link path=usr/share/man/man3proc/proc_get_ldt.3proc target=Pldt.3proc -link path=usr/share/man/man3proc/proc_lwp_range_valid.3proc target=proc_lwp_in_set.3proc -link path=usr/share/man/man3proc/proc_signame.3proc target=proc_fltname.3proc -link path=usr/share/man/man3proc/proc_sigset2str.3proc target=proc_fltset2str.3proc -link path=usr/share/man/man3proc/proc_str2content.3proc target=proc_content2str.3proc -link path=usr/share/man/man3proc/proc_str2sig.3proc target=proc_str2flt.3proc -link path=usr/share/man/man3proc/proc_str2sigset.3proc target=proc_str2fltset.3proc -link path=usr/share/man/man3proc/proc_str2sys.3proc target=proc_str2flt.3proc -link path=usr/share/man/man3proc/proc_str2sysset.3proc target=proc_str2fltset.3proc -link path=usr/share/man/man3proc/proc_sysname.3proc target=proc_fltname.3proc -link path=usr/share/man/man3proc/proc_sysset2str.3proc target=proc_fltset2str.3proc link path=usr/share/man/man3proc/Psetsysexit.3proc target=Psetsysentry.3proc link path=usr/share/man/man3proc/Pstop.3proc target=Pstopstatus.3proc -link path=usr/share/man/man3proc/Psymbol_iter_by_addr.3proc target=Psymbol_iter.3proc -link path=usr/share/man/man3proc/Psymbol_iter_by_lmid.3proc target=Psymbol_iter.3proc -link path=usr/share/man/man3proc/Psymbol_iter_by_name.3proc target=Psymbol_iter.3proc +link path=usr/share/man/man3proc/Psymbol_iter_by_addr.3proc \ + target=Psymbol_iter.3proc +link path=usr/share/man/man3proc/Psymbol_iter_by_lmid.3proc \ + target=Psymbol_iter.3proc +link path=usr/share/man/man3proc/Psymbol_iter_by_name.3proc \ + target=Psymbol_iter.3proc link path=usr/share/man/man3proc/Psysexit.3proc target=Psysentry.3proc link path=usr/share/man/man3proc/Punsetflags.3proc target=Psetflags.3proc link path=usr/share/man/man3proc/Pwait.3proc target=Pstopstatus.3proc link path=usr/share/man/man3proc/Pxcreate.3proc target=Pcreate.3proc link path=usr/share/man/man3proc/Pxecwapt.3proc target=Pxecbkpt.3proc -link path=usr/share/man/man3proc/Pxlookup_by_addr_resolved.3proc target=Plookup_by_addr.3proc -link path=usr/share/man/man3proc/Pxlookup_by_addr.3proc target=Plookup_by_addr.3proc -link path=usr/share/man/man3proc/Pxlookup_by_name.3proc target=Plookup_by_addr.3proc +link path=usr/share/man/man3proc/Pxlookup_by_addr.3proc \ + target=Plookup_by_addr.3proc +link path=usr/share/man/man3proc/Pxlookup_by_addr_resolved.3proc \ + target=Plookup_by_addr.3proc +link path=usr/share/man/man3proc/Pxlookup_by_name.3proc \ + target=Plookup_by_addr.3proc link path=usr/share/man/man3proc/Pxsymbol_iter.3proc target=Psymbol_iter.3proc link path=usr/share/man/man3proc/Pzonepath.3proc target=Pzonename.3proc link path=usr/share/man/man3proc/Pzoneroot.3proc target=Pzonename.3proc +link path=usr/share/man/man3proc/pr_fstat.3proc target=pr_stat.3proc +link path=usr/share/man/man3proc/pr_fstat64.3proc target=pr_stat.3proc +link path=usr/share/man/man3proc/pr_getrlimit64.3proc \ + target=pr_getrlimit.3proc +link path=usr/share/man/man3proc/pr_lstat.3proc target=pr_stat.3proc +link path=usr/share/man/man3proc/pr_lstat64.3proc target=pr_stat.3proc +link path=usr/share/man/man3proc/pr_setrlimit64.3proc \ + target=pr_setrlimit.3proc +link path=usr/share/man/man3proc/pr_stat64.3proc target=pr_stat.3proc +link path=usr/share/man/man3proc/proc_arg_xgrab.3proc \ + target=proc_arg_grab.3proc +link path=usr/share/man/man3proc/proc_arg_xpsinfo.3proc \ + target=proc_arg_psinfo.3proc +link path=usr/share/man/man3proc/proc_dmodelname.3proc \ + target=proc_fltname.3proc +link path=usr/share/man/man3proc/proc_fdinfo_free.3proc \ + target=proc_get_fdinfo.3proc +link path=usr/share/man/man3proc/proc_finistdio.3proc \ + target=proc_initstdio.3proc +link path=usr/share/man/man3proc/proc_flushstdio.3proc \ + target=proc_initstdio.3proc +link path=usr/share/man/man3proc/proc_free_priv.3proc \ + target=proc_get_priv.3proc +link path=usr/share/man/man3proc/proc_get_ldt.3proc target=Pldt.3proc +link path=usr/share/man/man3proc/proc_lwp_range_valid.3proc \ + target=proc_lwp_in_set.3proc +link path=usr/share/man/man3proc/proc_signame.3proc target=proc_fltname.3proc +link path=usr/share/man/man3proc/proc_sigset2str.3proc \ + target=proc_fltset2str.3proc +link path=usr/share/man/man3proc/proc_str2content.3proc \ + target=proc_content2str.3proc +link path=usr/share/man/man3proc/proc_str2sig.3proc target=proc_str2flt.3proc +link path=usr/share/man/man3proc/proc_str2sigset.3proc \ + target=proc_str2fltset.3proc +link path=usr/share/man/man3proc/proc_str2sys.3proc target=proc_str2flt.3proc +link path=usr/share/man/man3proc/proc_str2sysset.3proc \ + target=proc_str2fltset.3proc +link path=usr/share/man/man3proc/proc_sysname.3proc target=proc_fltname.3proc +link path=usr/share/man/man3proc/proc_sysset2str.3proc \ + target=proc_fltset2str.3proc +link path=usr/share/man/man3proc/ps_kill.3proc target=ps_pstop.3proc +link path=usr/share/man/man3proc/ps_lcontinue.3proc target=ps_pstop.3proc +link path=usr/share/man/man3proc/ps_lgetfpregs.3proc target=ps_lgetregs.3proc +link path=usr/share/man/man3proc/ps_lgetxregs.3proc target=ps_lgetregs.3proc +link path=usr/share/man/man3proc/ps_lgetxregsize.3proc \ + target=ps_lgetregs.3proc +link path=usr/share/man/man3proc/ps_lrolltoaddr.3proc target=ps_pstop.3proc +link path=usr/share/man/man3proc/ps_lsetfpregs.3proc target=ps_lgetregs.3proc +link path=usr/share/man/man3proc/ps_lsetregs.3proc target=ps_lgetregs.3proc +link path=usr/share/man/man3proc/ps_lsetxregs.3proc target=ps_lgetregs.3proc +link path=usr/share/man/man3proc/ps_lstop.3proc target=ps_pstop.3proc +link path=usr/share/man/man3proc/ps_pcontinue.3proc target=ps_pstop.3proc +link path=usr/share/man/man3proc/ps_pdread.3proc target=ps_pread.3proc +link path=usr/share/man/man3proc/ps_pdwrite.3proc target=ps_pread.3proc +link path=usr/share/man/man3proc/ps_pglobal_sym.3proc \ + target=ps_pglobal_lookup.3proc +link path=usr/share/man/man3proc/ps_ptread.3proc target=ps_pread.3proc +link path=usr/share/man/man3proc/ps_ptwrite.3proc target=ps_pread.3proc +link path=usr/share/man/man3proc/ps_pwrite.3proc target=ps_pread.3proc diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c index fbc87fea66..eefc4450ec 100644 --- a/usr/src/uts/common/exec/elf/elf_notes.c +++ b/usr/src/uts/common/exec/elf/elf_notes.c @@ -27,6 +27,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #include <sys/types.h> @@ -108,7 +109,7 @@ setup_note_header(Phdr *v, proc_t *p) + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word)) + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) + nlwp * roundup(sizeof (prlwpname_t), sizeof (Word)) - + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word)); + + nfd * roundup(sizeof (prfdinfo_core_t), sizeof (Word)); if (curproc->p_agenttp != NULL) { v[0].p_filesz += sizeof (Note) + @@ -350,7 +351,7 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, vnode_t *fvp; struct file *fp; vattr_t vattr; - prfdinfo_t fdinfo; + prfdinfo_core_t fdinfo; bzero(&fdinfo, sizeof (fdinfo)); diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h index de816d49e7..b010d6a37e 100644 --- a/usr/src/uts/common/fs/proc/prdata.h +++ b/usr/src/uts/common/fs/proc/prdata.h @@ -28,6 +28,7 @@ /* * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _SYS_PROC_PRDATA_H @@ -131,6 +132,8 @@ typedef enum prnodetype { PR_ROOTDIR, /* /proc/<pid>/root */ PR_FDDIR, /* /proc/<pid>/fd */ PR_FD, /* /proc/<pid>/fd/nn */ + PR_FDINFODIR, /* /proc/<pid>/fdinfo */ + PR_FDINFO, /* /proc/<pid>/fdinfo/nn */ PR_OBJECTDIR, /* /proc/<pid>/object */ PR_OBJECT, /* /proc/<pid>/object/xxx */ PR_LWPDIR, /* /proc/<pid>/lwp */ @@ -288,7 +291,7 @@ extern struct vnodeops *prvnodeops; * * pr_iol_initlist(&listhead, sizeof (*mp), n); * while (whatever) { - * mp = pr_iol_newbuf(&listhead, sizeof (*mp); + * mp = pr_iol_newbuf(&listhead, sizeof (*mp)); * ... * error = ... * } @@ -313,6 +316,7 @@ extern void pr_iol_initlist(list_t *head, size_t itemsize, int nitems); extern void * pr_iol_newbuf(list_t *head, size_t itemsize); extern int pr_iol_copyout_and_free(list_t *head, caddr_t *tgt, int errin); extern int pr_iol_uiomove_and_free(list_t *head, uio_t *uiop, int errin); +extern void pr_iol_freelist(list_t *); #if defined(_SYSCALL32_IMPL) @@ -347,6 +351,8 @@ extern void pr_setentryexit(proc_t *, sysset_t *, int); extern int pr_set(proc_t *, long); extern int pr_unset(proc_t *, long); extern void pr_sethold(prnode_t *, sigset_t *); +extern file_t *pr_getf(proc_t *, uint_t, short *); +extern void pr_releasef(proc_t *, uint_t); extern void pr_setfault(proc_t *, fltset_t *); extern int prusrio(proc_t *, enum uio_rw, struct uio *, int); extern int prwritectl(vnode_t *, struct uio *, cred_t *); diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c index a2ab06d769..ff6ba06d5b 100644 --- a/usr/src/uts/common/fs/proc/prsubr.c +++ b/usr/src/uts/common/fs/proc/prsubr.c @@ -22,10 +22,11 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ +/* All Rights Reserved */ #include <sys/types.h> #include <sys/t_lock.h> @@ -65,6 +66,18 @@ #include <sys/copyops.h> #include <sys/time.h> #include <sys/msacct.h> +#include <sys/flock_impl.h> +#include <sys/stropts.h> +#include <sys/strsubr.h> +#include <sys/pathname.h> +#include <sys/mode.h> +#include <sys/socketvar.h> +#include <sys/autoconf.h> +#include <sys/dtrace.h> +#include <sys/timod.h> +#include <netinet/udp.h> +#include <netinet/tcp.h> +#include <inet/cc.h> #include <vm/as.h> #include <vm/rm.h> #include <vm/seg.h> @@ -1454,6 +1467,57 @@ pr_u64tos(uint64_t n, char *s) return (len); } +file_t * +pr_getf(proc_t *p, uint_t fd, short *flag) +{ + uf_entry_t *ufp; + uf_info_t *fip; + file_t *fp; + + ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK)); + + fip = P_FINFO(p); + + if (fd >= fip->fi_nfiles) + return (NULL); + + mutex_exit(&p->p_lock); + mutex_enter(&fip->fi_lock); + UF_ENTER(ufp, fip, fd); + if ((fp = ufp->uf_file) != NULL && fp->f_count > 0) { + if (flag != NULL) + *flag = ufp->uf_flag; + ufp->uf_refcnt++; + } else { + fp = NULL; + } + UF_EXIT(ufp); + mutex_exit(&fip->fi_lock); + mutex_enter(&p->p_lock); + + return (fp); +} + +void +pr_releasef(proc_t *p, uint_t fd) +{ + uf_entry_t *ufp; + uf_info_t *fip; + + ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK)); + + fip = P_FINFO(p); + + mutex_exit(&p->p_lock); + mutex_enter(&fip->fi_lock); + UF_ENTER(ufp, fip, fd); + ASSERT3U(ufp->uf_refcnt, >, 0); + ufp->uf_refcnt--; + UF_EXIT(ufp); + mutex_exit(&fip->fi_lock); + mutex_enter(&p->p_lock); +} + void pr_object_name(char *name, vnode_t *vp, struct vattr *vattr) { @@ -1563,6 +1627,18 @@ pr_iol_newbuf(list_t *iolhead, size_t itemsize) return (new); } +void +pr_iol_freelist(list_t *iolhead) +{ + piol_t *iol; + + while ((iol = list_head(iolhead)) != NULL) { + list_remove(iolhead, iol); + kmem_free(iol, iol->piol_size); + } + list_destroy(iolhead); +} + int pr_iol_copyout_and_free(list_t *iolhead, caddr_t *tgt, int errin) { @@ -2375,6 +2451,481 @@ prgetpsinfo(proc_t *p, psinfo_t *psp) } } +static size_t +prfdinfomisc(list_t *data, uint_t type, const void *val, size_t vlen) +{ + pr_misc_header_t *misc; + size_t len; + + len = PRFDINFO_ROUNDUP(sizeof (*misc) + vlen); + + if (data != NULL) { + misc = pr_iol_newbuf(data, len); + misc->pr_misc_type = type; + misc->pr_misc_size = len; + misc++; + bcopy((char *)val, (char *)misc, vlen); + } + + return (len); +} + +/* + * There's no elegant way to determine if a character device + * supports TLI, so just check a hardcoded list of known TLI + * devices. + */ + +static boolean_t +pristli(vnode_t *vp) +{ + static const char *tlidevs[] = { + "udp", "udp6", "tcp", "tcp6" + }; + char *devname; + uint_t i; + + ASSERT(vp != NULL); + + if (vp->v_type != VCHR || vp->v_stream == NULL || vp->v_rdev == 0) + return (B_FALSE); + + if ((devname = mod_major_to_name(getmajor(vp->v_rdev))) == NULL) + return (B_FALSE); + + for (i = 0; i < ARRAY_SIZE(tlidevs); i++) { + if (strcmp(devname, tlidevs[i]) == 0) + return (B_TRUE); + } + + return (B_FALSE); +} + +static size_t +prfdinfopath(proc_t *p, vnode_t *vp, list_t *data, cred_t *cred) +{ + char *pathname; + vnode_t *vrootp; + size_t pathlen; + size_t sz = 0; + + pathlen = MAXPATHLEN + 1; + pathname = kmem_alloc(pathlen, KM_SLEEP); + + mutex_enter(&p->p_lock); + if ((vrootp = PTOU(p)->u_rdir) == NULL) + vrootp = rootdir; + VN_HOLD(vrootp); + mutex_exit(&p->p_lock); + + if (vnodetopath(vrootp, vp, pathname, pathlen, cred) == 0) { + sz += prfdinfomisc(data, PR_PATHNAME, + pathname, strlen(pathname) + 1); + } + VN_RELE(vrootp); + + kmem_free(pathname, pathlen); + return (sz); +} + +static size_t +prfdinfotlisockopt(vnode_t *vp, list_t *data, cred_t *cred) +{ + strcmd_t strcmd; + int32_t rval; + size_t sz = 0; + + strcmd.sc_cmd = TI_GETMYNAME; + strcmd.sc_timeout = 1; + strcmd.sc_len = STRCMDBUFSIZE; + + if (VOP_IOCTL(vp, _I_CMD, (intptr_t)&strcmd, FKIOCTL, cred, + &rval, NULL) == 0 && strcmd.sc_len > 0) { + sz += prfdinfomisc(data, PR_SOCKETNAME, strcmd.sc_buf, + strcmd.sc_len); + } + + strcmd.sc_cmd = TI_GETPEERNAME; + strcmd.sc_timeout = 1; + strcmd.sc_len = STRCMDBUFSIZE; + + if (VOP_IOCTL(vp, _I_CMD, (intptr_t)&strcmd, FKIOCTL, cred, + &rval, NULL) == 0 && strcmd.sc_len > 0) { + sz += prfdinfomisc(data, PR_PEERSOCKNAME, strcmd.sc_buf, + strcmd.sc_len); + } + + return (sz); +} + +static size_t +prfdinfosockopt(vnode_t *vp, list_t *data, cred_t *cred) +{ + sonode_t *so; + socklen_t vlen; + size_t sz = 0; + uint_t i; + + if (vp->v_stream != NULL) { + so = VTOSO(vp->v_stream->sd_vnode); + + if (so->so_version == SOV_STREAM) + so = NULL; + } else { + so = VTOSO(vp); + } + + if (so == NULL) + return (0); + + DTRACE_PROBE1(sonode, sonode_t *, so); + + /* prmisc - PR_SOCKETNAME */ + + struct sockaddr_storage buf; + struct sockaddr *name = (struct sockaddr *)&buf; + + vlen = sizeof (buf); + if (SOP_GETSOCKNAME(so, name, &vlen, cred) == 0 && vlen > 0) + sz += prfdinfomisc(data, PR_SOCKETNAME, name, vlen); + + /* prmisc - PR_PEERSOCKNAME */ + + vlen = sizeof (buf); + if (SOP_GETPEERNAME(so, name, &vlen, B_FALSE, cred) == 0 && vlen > 0) + sz += prfdinfomisc(data, PR_PEERSOCKNAME, name, vlen); + + /* prmisc - PR_SOCKOPTS_BOOL_OPTS */ + + static struct boolopt { + int level; + int opt; + int bopt; + } boolopts[] = { + { SOL_SOCKET, SO_DEBUG, PR_SO_DEBUG }, + { SOL_SOCKET, SO_REUSEADDR, PR_SO_REUSEADDR }, +#ifdef SO_REUSEPORT + /* SmartOS and OmniOS have SO_REUSEPORT */ + { SOL_SOCKET, SO_REUSEPORT, PR_SO_REUSEPORT }, +#endif + { SOL_SOCKET, SO_KEEPALIVE, PR_SO_KEEPALIVE }, + { SOL_SOCKET, SO_DONTROUTE, PR_SO_DONTROUTE }, + { SOL_SOCKET, SO_BROADCAST, PR_SO_BROADCAST }, + { SOL_SOCKET, SO_OOBINLINE, PR_SO_OOBINLINE }, + { SOL_SOCKET, SO_DGRAM_ERRIND, PR_SO_DGRAM_ERRIND }, + { SOL_SOCKET, SO_ALLZONES, PR_SO_ALLZONES }, + { SOL_SOCKET, SO_MAC_EXEMPT, PR_SO_MAC_EXEMPT }, + { SOL_SOCKET, SO_MAC_IMPLICIT, PR_SO_MAC_IMPLICIT }, + { SOL_SOCKET, SO_EXCLBIND, PR_SO_EXCLBIND }, + { SOL_SOCKET, SO_VRRP, PR_SO_VRRP }, + { IPPROTO_UDP, UDP_NAT_T_ENDPOINT, + PR_UDP_NAT_T_ENDPOINT } + }; + prsockopts_bool_opts_t opts; + int val; + + if (data != NULL) { + opts.prsock_bool_opts = 0; + + for (i = 0; i < ARRAY_SIZE(boolopts); i++) { + vlen = sizeof (val); + if (SOP_GETSOCKOPT(so, boolopts[i].level, + boolopts[i].opt, &val, &vlen, 0, cred) == 0 && + val != 0) { + opts.prsock_bool_opts |= boolopts[i].bopt; + } + } + } + + sz += prfdinfomisc(data, PR_SOCKOPTS_BOOL_OPTS, &opts, sizeof (opts)); + + /* prmisc - PR_SOCKOPT_LINGER */ + + struct linger l; + + vlen = sizeof (l); + if (SOP_GETSOCKOPT(so, SOL_SOCKET, SO_LINGER, &l, &vlen, + 0, cred) == 0 && vlen > 0) { + sz += prfdinfomisc(data, PR_SOCKOPT_LINGER, &l, vlen); + } + + /* prmisc - PR_SOCKOPT_* int types */ + + static struct sopt { + int level; + int opt; + int bopt; + } sopts[] = { + { SOL_SOCKET, SO_TYPE, PR_SOCKOPT_TYPE }, + { SOL_SOCKET, SO_SNDBUF, PR_SOCKOPT_SNDBUF }, + { SOL_SOCKET, SO_RCVBUF, PR_SOCKOPT_RCVBUF } + }; + + for (i = 0; i < ARRAY_SIZE(sopts); i++) { + vlen = sizeof (val); + if (SOP_GETSOCKOPT(so, sopts[i].level, sopts[i].opt, + &val, &vlen, 0, cred) == 0 && vlen > 0) { + sz += prfdinfomisc(data, sopts[i].bopt, &val, vlen); + } + } + + /* prmisc - PR_SOCKOPT_IP_NEXTHOP */ + + in_addr_t nexthop_val; + + vlen = sizeof (nexthop_val); + if (SOP_GETSOCKOPT(so, IPPROTO_IP, IP_NEXTHOP, + &nexthop_val, &vlen, 0, cred) == 0 && vlen > 0) { + sz += prfdinfomisc(data, PR_SOCKOPT_IP_NEXTHOP, + &nexthop_val, vlen); + } + + /* prmisc - PR_SOCKOPT_IPV6_NEXTHOP */ + + struct sockaddr_in6 nexthop6_val; + + vlen = sizeof (nexthop6_val); + if (SOP_GETSOCKOPT(so, IPPROTO_IPV6, IPV6_NEXTHOP, + &nexthop6_val, &vlen, 0, cred) == 0 && vlen > 0) { + sz += prfdinfomisc(data, PR_SOCKOPT_IPV6_NEXTHOP, + &nexthop6_val, vlen); + } + + /* prmisc - PR_SOCKOPT_TCP_CONGESTION */ + + char cong[CC_ALGO_NAME_MAX]; + + vlen = sizeof (cong); + if (SOP_GETSOCKOPT(so, IPPROTO_TCP, TCP_CONGESTION, + &cong, &vlen, 0, cred) == 0 && vlen > 0) { + sz += prfdinfomisc(data, PR_SOCKOPT_TCP_CONGESTION, cong, vlen); + } + + /* prmisc - PR_SOCKFILTERS_PRIV */ + + struct fil_info fi; + + vlen = sizeof (fi); + if (SOP_GETSOCKOPT(so, SOL_FILTER, FIL_LIST, + &fi, &vlen, 0, cred) == 0 && vlen != 0) { + pr_misc_header_t *misc; + size_t len; + + /* + * We limit the number of returned filters to 32. + * This is the maximum number that pfiles will print + * anyway. + */ + vlen = MIN(32, fi.fi_pos + 1); + vlen *= sizeof (fi); + + len = PRFDINFO_ROUNDUP(sizeof (*misc) + vlen); + sz += len; + + if (data != NULL) { + /* + * So that the filter list can be built incrementally, + * prfdinfomisc() is not used here. Instead we + * allocate a buffer directly on the copyout list using + * pr_iol_newbuf() + */ + misc = pr_iol_newbuf(data, len); + misc->pr_misc_type = PR_SOCKFILTERS_PRIV; + misc->pr_misc_size = len; + misc++; + len = vlen; + if (SOP_GETSOCKOPT(so, SOL_FILTER, FIL_LIST, + misc, &vlen, 0, cred) == 0) { + /* + * In case the number of filters has reduced + * since the first call, explicitly zero out + * any unpopulated space. + */ + if (vlen < len) + bzero(misc + vlen, len - vlen); + } else { + /* Something went wrong, zero out the result */ + bzero(misc, vlen); + } + } + } + + return (sz); +} + +u_offset_t +prgetfdinfosize(proc_t *p, vnode_t *vp, cred_t *cred) +{ + u_offset_t sz; + + /* + * All fdinfo files will be at least this big - + * sizeof fdinfo struct + zero length trailer + */ + sz = offsetof(prfdinfo_t, pr_misc) + sizeof (pr_misc_header_t); + + /* Pathname */ + if (vp->v_type != VSOCK && vp->v_type != VDOOR) + sz += prfdinfopath(p, vp, NULL, cred); + + /* Socket options */ + if (vp->v_type == VSOCK) + sz += prfdinfosockopt(vp, NULL, cred); + + /* TLI/XTI sockets */ + if (pristli(vp)) + sz += prfdinfotlisockopt(vp, NULL, cred); + + return (sz); +} + +int +prgetfdinfo(proc_t *p, vnode_t *vp, prfdinfo_t *fdinfo, cred_t *cred, + list_t *data) +{ + vattr_t vattr; + int error; + + /* + * The buffer has been initialised to zero by pr_iol_newbuf(). + * Initialise defaults for any values that should not default to zero. + */ + fdinfo->pr_uid = (uid_t)-1; + fdinfo->pr_gid = (gid_t)-1; + fdinfo->pr_size = -1; + fdinfo->pr_locktype = F_UNLCK; + fdinfo->pr_lockpid = -1; + fdinfo->pr_locksysid = -1; + fdinfo->pr_peerpid = -1; + + /* Offset */ + + /* + * pr_offset has already been set from the underlying file_t. + * Check if it is plausible and reset to -1 if not. + */ + if (fdinfo->pr_offset != -1 && + VOP_SEEK(vp, 0, (offset_t *)&fdinfo->pr_offset, NULL) != 0) + fdinfo->pr_offset = -1; + + /* Attributes */ + vattr.va_mask = AT_STAT; + if (VOP_GETATTR(vp, &vattr, 0, cred, NULL) == 0) { + fdinfo->pr_major = getmajor(vattr.va_fsid); + fdinfo->pr_minor = getminor(vattr.va_fsid); + fdinfo->pr_rmajor = getmajor(vattr.va_rdev); + fdinfo->pr_rminor = getminor(vattr.va_rdev); + fdinfo->pr_ino = (ino64_t)vattr.va_nodeid; + fdinfo->pr_size = (off64_t)vattr.va_size; + fdinfo->pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode; + fdinfo->pr_uid = vattr.va_uid; + fdinfo->pr_gid = vattr.va_gid; + if (vp->v_type == VSOCK) + fdinfo->pr_fileflags |= sock_getfasync(vp); + } + + /* locks */ + + flock64_t bf; + + bzero(&bf, sizeof (bf)); + bf.l_type = F_WRLCK; + + if (VOP_FRLOCK(vp, F_GETLK, &bf, + (uint16_t)(fdinfo->pr_fileflags & 0xffff), 0, NULL, + cred, NULL) == 0 && bf.l_type != F_UNLCK) { + fdinfo->pr_locktype = bf.l_type; + fdinfo->pr_lockpid = bf.l_pid; + fdinfo->pr_locksysid = bf.l_sysid; + } + + /* peer cred */ + + k_peercred_t kpc; + + switch (vp->v_type) { + case VFIFO: + case VSOCK: { + int32_t rval; + + error = VOP_IOCTL(vp, _I_GETPEERCRED, (intptr_t)&kpc, + FKIOCTL, cred, &rval, NULL); + break; + } + case VCHR: { + struct strioctl strioc; + int32_t rval; + + if (vp->v_stream == NULL) { + error = ENOTSUP; + break; + } + strioc.ic_cmd = _I_GETPEERCRED; + strioc.ic_timout = INFTIM; + strioc.ic_len = (int)sizeof (k_peercred_t); + strioc.ic_dp = (char *)&kpc; + + error = strdoioctl(vp->v_stream, &strioc, FNATIVE | FKIOCTL, + STR_NOSIG | K_TO_K, cred, &rval); + break; + } + default: + error = ENOTSUP; + break; + } + + if (error == 0 && kpc.pc_cr != NULL) { + proc_t *peerp; + + fdinfo->pr_peerpid = kpc.pc_cpid; + + crfree(kpc.pc_cr); + + mutex_enter(&pidlock); + if ((peerp = prfind(fdinfo->pr_peerpid)) != NULL) { + user_t *up; + + mutex_enter(&peerp->p_lock); + mutex_exit(&pidlock); + + up = PTOU(peerp); + bcopy(up->u_comm, fdinfo->pr_peername, + MIN(sizeof (up->u_comm), + sizeof (fdinfo->pr_peername) - 1)); + + mutex_exit(&peerp->p_lock); + } else { + mutex_exit(&pidlock); + } + } + + /* + * Don't attempt to determine the vnode path for a socket or a door + * as it will cause a linear scan of the dnlc table given there is no + * v_path associated with the vnode. + */ + if (vp->v_type != VSOCK && vp->v_type != VDOOR) + (void) prfdinfopath(p, vp, data, cred); + + if (vp->v_type == VSOCK) + (void) prfdinfosockopt(vp, data, cred); + + /* TLI/XTI stream sockets */ + if (pristli(vp)) + (void) prfdinfotlisockopt(vp, data, cred); + + /* + * Add a terminating header with a zero size. + */ + pr_misc_header_t *misc; + + misc = pr_iol_newbuf(data, sizeof (*misc)); + misc->pr_misc_size = 0; + misc->pr_misc_type = (uint_t)-1; + + return (0); +} + #ifdef _SYSCALL32_IMPL void prgetpsinfo32(proc_t *p, psinfo32_t *psp) @@ -2670,7 +3221,7 @@ prgetlwpsinfo32(kthread_t *t, lwpsinfo32_t *psp) #define PR_COPY_TIMESPEC(s, d, field) \ TIMESPEC_TO_TIMESPEC32(&d->field, &s->field); -#define PR_COPY_BUF(s, d, field) \ +#define PR_COPY_BUF(s, d, field) \ bcopy(s->field, d->field, sizeof (d->field)); #define PR_IGNORE_FIELD(s, d, field) diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c index 2cf007c42c..a324181683 100644 --- a/usr/src/uts/common/fs/proc/prvnops.c +++ b/usr/src/uts/common/fs/proc/prvnops.c @@ -23,6 +23,7 @@ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, Joyent, Inc. * Copyright (c) 2017 by Delphix. All rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -154,20 +155,22 @@ static prdirent_t piddir[] = { "root" }, { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t), "fd" }, - { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t), + "fdinfo" }, + { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t), "object" }, - { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_LWPDIR, 24 * sizeof (prdirent_t), sizeof (prdirent_t), "lwp" }, - { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_PRIV, 25 * sizeof (prdirent_t), sizeof (prdirent_t), "priv" }, - { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_PATHDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t), "path" }, - { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_CTDIR, 27 * sizeof (prdirent_t), sizeof (prdirent_t), "contracts" }, - { PR_SECFLAGS, 27 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_SECFLAGS, 28 * sizeof (prdirent_t), sizeof (prdirent_t), "secflags" }, #if defined(__x86) - { PR_LDT, 28 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_LDT, 29 * sizeof (prdirent_t), sizeof (prdirent_t), "ldt" }, #endif }; @@ -596,7 +599,8 @@ static int pr_read_inval(), pr_read_as(), pr_read_status(), #if defined(__sparc) pr_read_gwindows(), pr_read_asrs(), #endif - pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(); + pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(), + pr_read_fdinfo(); static int (*pr_read_function[PR_NFILES])() = { pr_read_inval, /* /proc */ @@ -625,6 +629,8 @@ static int (*pr_read_function[PR_NFILES])() = { pr_read_inval, /* /proc/<pid>/root */ pr_read_inval, /* /proc/<pid>/fd */ pr_read_inval, /* /proc/<pid>/fd/nn */ + pr_read_inval, /* /proc/<pid>/fdinfo */ + pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */ pr_read_inval, /* /proc/<pid>/object */ pr_read_inval, /* /proc/<pid>/object/xxx */ pr_read_inval, /* /proc/<pid>/lwp */ @@ -813,6 +819,95 @@ pr_read_psinfo(prnode_t *pnp, uio_t *uiop) } static int +pr_read_fdinfo(prnode_t *pnp, uio_t *uiop) +{ + prfdinfo_t *fdinfo; + list_t data; + proc_t *p; + vnode_t *vp; + uint_t fd; + file_t *fp; + cred_t *cred; + short ufp_flag; + int error = 0; + + ASSERT(pnp->pr_type == PR_FDINFO); + + /* + * This is a guess at the size of the structure that needs to + * be returned. It's a balance between not allocating too much more + * space than is required and not requiring too many subsequent + * reallocations. Allocate it before acquiring the process lock. + */ + pr_iol_initlist(&data, sizeof (prfdinfo_t) + MAXPATHLEN + 2, 1); + + if ((error = prlock(pnp, ZNO)) != 0) { + pr_iol_freelist(&data); + return (error); + } + + p = pnp->pr_common->prc_proc; + + if ((p->p_flag & SSYS) || p->p_as == &kas) { + prunlock(pnp); + pr_iol_freelist(&data); + return (0); + } + + fd = pnp->pr_index; + + /* Fetch and lock the file_t for this descriptor */ + fp = pr_getf(p, fd, &ufp_flag); + + if (fp == NULL) { + error = ENOENT; + prunlock(pnp); + goto out; + } + + vp = fp->f_vnode; + VN_HOLD(vp); + + /* + * For fdinfo, we don't want to include the placeholder pr_misc at the + * end of the struct. We'll terminate the data with an empty pr_misc + * header before returning. + */ + + fdinfo = pr_iol_newbuf(&data, offsetof(prfdinfo_t, pr_misc)); + fdinfo->pr_fd = fd; + fdinfo->pr_fdflags = ufp_flag; + /* FEPOLLED on f_flag2 should never be user-visible */ + fdinfo->pr_fileflags = (fp->f_flag2 & ~FEPOLLED) << 16 | fp->f_flag; + if ((fdinfo->pr_fileflags & (FSEARCH | FEXEC)) == 0) + fdinfo->pr_fileflags += FOPEN; + fdinfo->pr_offset = fp->f_offset; + cred = fp->f_cred; + crhold(cred); + /* + * Information from the vnode (rather than the file_t) is retrieved + * later, in prgetfdinfo() - for example sock_getfasync() + */ + pr_releasef(p, fd); + + prunlock(pnp); + + error = prgetfdinfo(p, vp, fdinfo, cred, &data); + + crfree(cred); + + VN_RELE(vp); + +out: + if (error == 0) + error = pr_iol_uiomove_and_free(&data, uiop, error); + else + pr_iol_freelist(&data); + + return (error); +} + +static int pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop) { proc_t *p; @@ -1835,6 +1930,8 @@ static int (*pr_read_function_32[PR_NFILES])() = { pr_read_inval, /* /proc/<pid>/root */ pr_read_inval, /* /proc/<pid>/fd */ pr_read_inval, /* /proc/<pid>/fd/nn */ + pr_read_inval, /* /proc/<pid>/fdinfo */ + pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */ pr_read_inval, /* /proc/<pid>/object */ pr_read_inval, /* /proc/<pid>/object/xxx */ pr_read_inval, /* /proc/<pid>/lwp */ @@ -3080,9 +3177,29 @@ prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, vap->va_size = 0; break; case PR_FDDIR: + case PR_FDINFODIR: vap->va_nlink = 2; vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE; break; + case PR_FDINFO: { + file_t *fp; + vnode_t *vp; + int fd = pnp->pr_index; + + fp = pr_getf(p, fd, NULL); + if (fp == NULL) { + prunlock(pnp); + return (ENOENT); + } + vp = fp->f_vnode; + VN_HOLD(vp); + pr_releasef(p, fd); + prunlock(pnp); + vap->va_size = prgetfdinfosize(p, vp, cr); + VN_RELE(vp); + vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size); + return (0); + } case PR_LWPDIR: /* * va_nlink: count each lwp as a directory link. @@ -3407,8 +3524,8 @@ praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) */ static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(), *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(), - *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(), - *pr_lookup_ctdir(); + *pr_lookup_fddir(), *pr_lookup_fdinfodir(), *pr_lookup_pathdir(), + *pr_lookup_tmpldir(), *pr_lookup_ctdir(); static vnode_t *(*pr_lookup_function[PR_NFILES])() = { pr_lookup_procdir, /* /proc */ @@ -3437,6 +3554,8 @@ static vnode_t *(*pr_lookup_function[PR_NFILES])() = { pr_lookup_notdir, /* /proc/<pid>/root */ pr_lookup_fddir, /* /proc/<pid>/fd */ pr_lookup_notdir, /* /proc/<pid>/fd/nn */ + pr_lookup_fdinfodir, /* /proc/<pid>/fdinfo */ + pr_lookup_notdir, /* /proc/<pid>/fdinfo/nn */ pr_lookup_objectdir, /* /proc/<pid>/object */ pr_lookup_notdir, /* /proc/<pid>/object/xxx */ pr_lookup_lwpdir, /* /proc/<pid>/lwp */ @@ -3524,7 +3643,8 @@ prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp, break; } - if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) && + if ((type == PR_OBJECTDIR || type == PR_FDDIR || + type == PR_FDINFODIR || type == PR_PATHDIR) && (error = praccess(dp, VEXEC, 0, cr, ct)) != 0) return (error); @@ -4138,8 +4258,6 @@ pr_lookup_fddir(vnode_t *dp, char *comp) file_t *fp; uint_t fd; int c; - uf_entry_t *ufp; - uf_info_t *fip; ASSERT(dpnp->pr_type == PR_FDDIR); @@ -4149,8 +4267,8 @@ pr_lookup_fddir(vnode_t *dp, char *comp) if (c < '0' || c > '9') return (NULL); ofd = fd; - fd = 10*fd + c - '0'; - if (fd/10 != ofd) /* integer overflow */ + fd = 10 * fd + c - '0'; + if (fd / 10 != ofd) /* integer overflow */ return (NULL); } @@ -4167,49 +4285,98 @@ pr_lookup_fddir(vnode_t *dp, char *comp) return (NULL); } - fip = P_FINFO(p); - mutex_exit(&p->p_lock); - mutex_enter(&fip->fi_lock); - if (fd < fip->fi_nfiles) { - UF_ENTER(ufp, fip, fd); - if ((fp = ufp->uf_file) != NULL) { - pnp->pr_mode = 07111; - if (fp->f_flag & FREAD) - pnp->pr_mode |= 0444; - if (fp->f_flag & FWRITE) - pnp->pr_mode |= 0222; - vp = fp->f_vnode; - VN_HOLD(vp); - } - UF_EXIT(ufp); + if ((fp = pr_getf(p, fd, NULL)) != NULL) { + pnp->pr_mode = 07111; + if (fp->f_flag & FREAD) + pnp->pr_mode |= 0444; + if (fp->f_flag & FWRITE) + pnp->pr_mode |= 0222; + vp = fp->f_vnode; + VN_HOLD(vp); + pr_releasef(p, fd); } - mutex_exit(&fip->fi_lock); - mutex_enter(&p->p_lock); + prunlock(dpnp); - if (vp == NULL) + if (vp == NULL) { prfreenode(pnp); - else { - /* - * Fill in the prnode so future references will - * be able to find the underlying object's vnode. - * Don't link this prnode into the list of all - * prnodes for the process; this is a one-use node. - */ - pnp->pr_realvp = vp; - pnp->pr_parent = dp; /* needed for prlookup */ - VN_HOLD(dp); - vp = PTOV(pnp); - if (pnp->pr_realvp->v_type == VDIR) { - vp->v_type = VDIR; - vp->v_flag |= VTRAVERSE; - } + return (NULL); + } + + /* + * Fill in the prnode so future references will + * be able to find the underlying object's vnode. + * Don't link this prnode into the list of all + * prnodes for the process; this is a one-use node. + */ + pnp->pr_realvp = vp; + pnp->pr_parent = dp; /* needed for prlookup */ + VN_HOLD(dp); + vp = PTOV(pnp); + if (pnp->pr_realvp->v_type == VDIR) { + vp->v_type = VDIR; + vp->v_flag |= VTRAVERSE; } return (vp); } static vnode_t * +pr_lookup_fdinfodir(vnode_t *dp, char *comp) +{ + prnode_t *dpnp = VTOP(dp); + prnode_t *pnp; + vnode_t *vp = NULL; + proc_t *p; + uint_t fd; + int c; + + ASSERT(dpnp->pr_type == PR_FDINFODIR); + + fd = 0; + while ((c = *comp++) != '\0') { + int ofd; + if (c < '0' || c > '9') + return (NULL); + ofd = fd; + fd = 10 * fd + c - '0'; + if (fd / 10 != ofd) /* integer overflow */ + return (NULL); + } + + pnp = prgetnode(dp, PR_FDINFO); + + if (prlock(dpnp, ZNO) != 0) { + prfreenode(pnp); + return (NULL); + } + p = dpnp->pr_common->prc_proc; + if ((p->p_flag & SSYS) || p->p_as == &kas) { + prunlock(dpnp); + prfreenode(pnp); + return (NULL); + } + + /* + * Don't link this prnode into the list of all + * prnodes for the process; this is a one-use node. + * Unlike the FDDIR case, the underlying vnode is not stored in + * pnp->pr_realvp. Instead, the fd number is stored in pnp->pr_index + * and used by pr_read_fdinfo() to return information for the right + * file descriptor. + */ + pnp->pr_common = dpnp->pr_common; + pnp->pr_pcommon = dpnp->pr_pcommon; + pnp->pr_parent = dp; + pnp->pr_index = fd; + VN_HOLD(dp); + prunlock(dpnp); + vp = PTOV(pnp); + + return (vp); +} + +static vnode_t * pr_lookup_pathdir(vnode_t *dp, char *comp) { prnode_t *dpnp = VTOP(dp); @@ -4667,6 +4834,7 @@ prgetnode(vnode_t *dp, prnodetype_t type) case PR_CURDIR: case PR_ROOTDIR: case PR_FDDIR: + case PR_FDINFODIR: case PR_OBJECTDIR: case PR_PATHDIR: case PR_CTDIR: @@ -4799,8 +4967,8 @@ prfreecommon(prcommon_t *pcp) */ static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(), pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(), - pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(), - pr_readdir_ctdir(); + pr_readdir_fddir(), pr_readdir_fdinfodir(), pr_readdir_pathdir(), + pr_readdir_tmpldir(), pr_readdir_ctdir(); static int (*pr_readdir_function[PR_NFILES])() = { pr_readdir_procdir, /* /proc */ @@ -4829,6 +4997,8 @@ static int (*pr_readdir_function[PR_NFILES])() = { pr_readdir_notdir, /* /proc/<pid>/root */ pr_readdir_fddir, /* /proc/<pid>/fd */ pr_readdir_notdir, /* /proc/<pid>/fd/nn */ + pr_readdir_fdinfodir, /* /proc/<pid>/fdinfo */ + pr_readdir_notdir, /* /proc/<pid>/fdinfo/nn */ pr_readdir_objectdir, /* /proc/<pid>/object */ pr_readdir_notdir, /* /proc/<pid>/object/xxx */ pr_readdir_lwpdir, /* /proc/<pid>/lwp */ @@ -5361,9 +5531,12 @@ out: return (0); } -/* ARGSUSED */ +/* + * Helper function for reading a directory which lists open file desciptors + */ static int -pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp) +pr_readdir_fdlist(prnode_t *pnp, uio_t *uiop, int *eofp, + prnodetype_t dirtype, prnodetype_t entrytype) { gfs_readdir_state_t gstate; int error, eof = 0; @@ -5373,8 +5546,6 @@ pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp) int fddirsize; uf_info_t *fip; - ASSERT(pnp->pr_type == PR_FDDIR); - if ((error = prlock(pnp, ZNO)) != 0) return (error); p = pnp->pr_common->prc_proc; @@ -5383,7 +5554,7 @@ pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp) mutex_exit(&p->p_lock); if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop, - pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) { + pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, dirtype), 0)) != 0) { mutex_enter(&p->p_lock); prunlock(pnp); return (error); @@ -5414,7 +5585,7 @@ pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp) } error = gfs_readdir_emitn(&gstate, uiop, n, - pmkino(n, pslot, PR_FD), n); + pmkino(n, pslot, entrytype), n); if (error) break; } @@ -5426,6 +5597,24 @@ pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp) return (gfs_readdir_fini(&gstate, error, eofp, eof)); } +static int +pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp) +{ + + ASSERT(pnp->pr_type == PR_FDDIR); + + return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FD)); +} + +static int +pr_readdir_fdinfodir(prnode_t *pnp, uio_t *uiop, int *eofp) +{ + + ASSERT(pnp->pr_type == PR_FDINFODIR); + + return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FDINFO)); +} + /* ARGSUSED */ static int pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp) @@ -5735,6 +5924,7 @@ prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) switch (type) { case PR_OBJECT: case PR_FD: + case PR_FDINFO: case PR_SELF: case PR_PATH: /* These are not linked into the usual lists */ diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h index dfb54eaef5..ea485c09fd 100644 --- a/usr/src/uts/common/sys/procfs.h +++ b/usr/src/uts/common/sys/procfs.h @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _SYS_PROCFS_H @@ -505,7 +506,7 @@ typedef struct prasmap { #define PG_HWMAPPED 0x04 /* page is present and mapped */ /* - * Open files. Only in core files (for now). Note that we'd like to use + * Open file information; used in core files. Note that we'd like to use * the stat or stat64 structure, but both of these structures are unfortunately * not consistent between 32 and 64 bit modes. To keep our lives simpler, we * just define our own structure with types that are not sensitive to this @@ -513,7 +514,7 @@ typedef struct prasmap { * struct stat (e.g. times, device sizes, etc.) so we don't bother adding those * here. */ -typedef struct prfdinfo { +typedef struct prfdinfo_core { int pr_fd; mode_t pr_mode; @@ -534,8 +535,97 @@ typedef struct prfdinfo { int pr_fdflags; /* fcntl(F_GETFD), etc. */ char pr_path[MAXPATHLEN]; +} prfdinfo_core_t; + +/* + * Open file information; used in /proc/<pid>/fdinfo/nn files. + * This differs from prfdinfo_core_t above as it exposes more information + * and is variable length, with the last element, pr_misc, pointing to an + * array of miscellaneous data items. + */ + +typedef struct prfdinfo { + int pr_fd; /* file descriptor number */ + mode_t pr_mode; /* (see st_mode in stat(2)) */ + ino64_t pr_ino; /* inode number */ + off64_t pr_size; /* file size */ + off64_t pr_offset; /* current offset of file descriptor */ + uid_t pr_uid; /* owner's user id */ + gid_t pr_gid; /* owner's group id */ + major_t pr_major; /* major number of device */ + minor_t pr_minor; /* minor number of device */ + major_t pr_rmajor; /* major number (if special file) */ + minor_t pr_rminor; /* minor number (if special file) */ + int pr_fileflags; /* (see F_GETXFL in fcntl(2)) */ + int pr_fdflags; /* (see F_GETFD in fcntl(2)) */ + short pr_locktype; /* (see F_GETLK in fcntl(2)) */ + pid_t pr_lockpid; /* process holding file lock */ + /* (see F_GETLK) */ + int pr_locksysid; /* sysid of locking process */ + /* (see F_GETLK) */ + pid_t pr_peerpid; /* peer process (socket, door) */ + int pr_filler[25]; /* reserved for future use */ + char pr_peername[PRFNSZ]; /* peer process name */ +#if __STDC_VERSION__ >= 199901L + uint8_t pr_misc[]; /* self describing structures */ +#else + uint8_t pr_misc[1]; /* self describing structures */ +#endif } prfdinfo_t; +/* pr_misc item size is rounded up to maintain alignment */ +#define PRFDINFO_ROUNDUP(num) P2ROUNDUP((num), 4) + +typedef struct pr_misc_header { + uint_t pr_misc_size; + uint_t pr_misc_type; +} pr_misc_header_t; + +/* + * The gaps in this enumeration are present to maintain compatibility with + * the values used in Solaris. Any future illumos-specific additions to this + * list should use the PR_ILLUMOS_ prefix, be placed after PR_MISC_TYPES_MAX + * and start from a number sufficiently large enough to leave space for any + * future additions in Solaris. + */ + +enum PR_MISC_TYPES { + PR_PATHNAME, + PR_SOCKETNAME, + PR_PEERSOCKNAME, + PR_SOCKOPTS_BOOL_OPTS, + PR_SOCKOPT_LINGER, + PR_SOCKOPT_SNDBUF, + PR_SOCKOPT_RCVBUF, + PR_SOCKOPT_IP_NEXTHOP, + PR_SOCKOPT_IPV6_NEXTHOP, + PR_SOCKOPT_TYPE, + PR_SOCKOPT_TCP_CONGESTION = 11, + PR_SOCKFILTERS_PRIV = 14, + PR_MISC_TYPES_MAX +}; + +typedef struct prsockopts_bool_opts { + unsigned int prsock_bool_opts; +} prsockopts_bool_opts_t; + +#define PR_SO_DEBUG (1 << 0) +#define PR_SO_REUSEADDR (1 << 1) +#define PR_SO_REUSEPORT (1 << 2) +#define PR_SO_KEEPALIVE (1 << 3) +#define PR_SO_DONTROUTE (1 << 4) +#define PR_SO_BROADCAST (1 << 5) +#define PR_SO_OOBINLINE (1 << 7) +#define PR_SO_DGRAM_ERRIND (1 << 8) +#define PR_SO_ALLZONES (1 << 9) +#define PR_SO_MAC_EXEMPT (1 << 10) +#define PR_SO_EXCLBIND (1 << 11) +#define PR_SO_PASSIVE_CONNECT (1 << 12) +#define PR_SO_ACCEPTCONN (1 << 13) +#define PR_UDP_NAT_T_ENDPOINT (1 << 14) +#define PR_SO_VRRP (1 << 15) +#define PR_SO_MAC_IMPLICIT (1 << 16) + /* * Representation of LWP name in core files. In /proc, we use a simple char * array, but in core files we need to make it easy to correlate the note back diff --git a/usr/src/uts/common/sys/prsystm.h b/usr/src/uts/common/sys/prsystm.h index 7adc920da2..9aa047740a 100644 --- a/usr/src/uts/common/sys/prsystm.h +++ b/usr/src/uts/common/sys/prsystm.h @@ -29,6 +29,7 @@ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _SYS_PRSYSTM_H @@ -54,6 +55,7 @@ struct lwpsinfo; struct prcred; struct prpriv; struct prsecflags; +struct prfdinfo; struct seg; struct regs; @@ -77,16 +79,14 @@ extern void prgetlwpsinfo(kthread_t *, struct lwpsinfo *); extern void prgetprfpregs(klwp_t *, struct prfpregset *); extern void prgetprxregs(klwp_t *, caddr_t); extern int prgetprxregsize(proc_t *); -#if defined(__lint) -/* Work around lint confusion between old and new prcred definitions */ -extern void prgetcred(); -#else extern void prgetcred(proc_t *, struct prcred *); -#endif extern void prgetpriv(proc_t *, struct prpriv *); extern size_t prgetprivsize(void); extern void prgetsecflags(proc_t *, struct prsecflags *); extern int prnsegs(struct as *, int); +extern u_offset_t prgetfdinfosize(proc_t *, vnode_t *, cred_t *); +extern int prgetfdinfo(proc_t *, vnode_t *, struct prfdinfo *, cred_t *, + list_t *); extern void prexit(proc_t *); extern void prfree(proc_t *); extern void prlwpexit(kthread_t *); |