| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
1 | /* |
| 2 | * Copyright (c) 1993 Jan-Simon Pendry | |
| 3 | * Copyright (c) 1993 | |
| 4 | * The Regents of the University of California. All rights reserved. | |
| 5 | * | |
| 6 | * This code is derived from software contributed to Berkeley by | |
| 7 | * Jan-Simon Pendry. | |
| 8 | * | |
| 9 | * Redistribution and use in source and binary forms, with or without | |
| 10 | * modification, are permitted provided that the following conditions | |
| 11 | * are met: | |
| 12 | * 1. Redistributions of source code must retain the above copyright | |
| 13 | * notice, this list of conditions and the following disclaimer. | |
| 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 15 | * notice, this list of conditions and the following disclaimer in the | |
| 16 | * documentation and/or other materials provided with the distribution. | |
| 17 | * 3. All advertising materials mentioning features or use of this software | |
| 18 | * must display the following acknowledgement: | |
| 19 | * This product includes software developed by the University of | |
| 20 | * California, Berkeley and its contributors. | |
| 21 | * 4. Neither the name of the University nor the names of its contributors | |
| 22 | * may be used to endorse or promote products derived from this software | |
| 23 | * without specific prior written permission. | |
| 24 | * | |
| 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 35 | * SUCH DAMAGE. | |
| 36 | * | |
| 37 | * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 | |
| 38 | * | |
| 39 | * From: | |
| 40 | * $FreeBSD: src/sys/miscfs/procfs/procfs_status.c,v 1.20.2.4 2002/01/22 17:22:59 nectar Exp $ | |
| c7e98b2f | 41 | * $DragonFly: src/sys/vfs/procfs/procfs_status.c,v 1.15 2007/02/19 01:14:24 corecode Exp $ |
| 984263bc MD |
42 | */ |
| 43 | ||
| 44 | #include <sys/param.h> | |
| 45 | #include <sys/systm.h> | |
| 46 | #include <sys/malloc.h> | |
| 47 | #include <sys/proc.h> | |
| 75bda2d9 | 48 | #include <sys/priv.h> |
| 984263bc MD |
49 | #include <sys/jail.h> |
| 50 | #include <sys/vnode.h> | |
| 51 | #include <sys/tty.h> | |
| 52 | #include <sys/resourcevar.h> | |
| 1f2de5d4 | 53 | #include <vfs/procfs/procfs.h> |
| 984263bc MD |
54 | |
| 55 | #include <vm/vm.h> | |
| 56 | #include <vm/pmap.h> | |
| 57 | #include <vm/vm_param.h> | |
| 58 | #include <sys/exec.h> | |
| 59 | ||
| 60 | #define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0) | |
| 61 | int | |
| c7e98b2f | 62 | procfs_dostatus(struct proc *curp, struct lwp *lp, struct pfsnode *pfs, |
| ac424f9b | 63 | struct uio *uio) |
| 984263bc | 64 | { |
| c7e98b2f | 65 | struct proc *p = lp->lwp_proc; |
| 984263bc MD |
66 | struct session *sess; |
| 67 | struct tty *tp; | |
| 68 | struct ucred *cr; | |
| 69 | char *ps; | |
| 70 | char *sep; | |
| 71 | int pid, ppid, pgid, sid; | |
| e54488bb | 72 | size_t xlen; |
| 984263bc | 73 | int i; |
| 984263bc MD |
74 | int error; |
| 75 | char psbuf[256]; /* XXX - conservative */ | |
| 76 | ||
| 77 | if (uio->uio_rw != UIO_READ) | |
| 78 | return (EOPNOTSUPP); | |
| 79 | ||
| 80 | pid = p->p_pid; | |
| 81 | ppid = p->p_pptr ? p->p_pptr->p_pid : 0; | |
| 82 | pgid = p->p_pgrp->pg_id; | |
| 83 | sess = p->p_pgrp->pg_session; | |
| 84 | sid = sess->s_leader ? sess->s_leader->p_pid : 0; | |
| 85 | ||
| 86 | /* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg | |
| 87 | euid ruid rgid,egid,groups[1 .. NGROUPS] | |
| 88 | */ | |
| 89 | KASSERT(sizeof(psbuf) > MAXCOMLEN, | |
| 90 | ("Too short buffer for new MAXCOMLEN")); | |
| 91 | ||
| 92 | ps = psbuf; | |
| 93 | bcopy(p->p_comm, ps, MAXCOMLEN); | |
| 94 | ps[MAXCOMLEN] = '\0'; | |
| 95 | ps += strlen(ps); | |
| 96 | DOCHECK(); | |
| f8c7a42d | 97 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 984263bc MD |
98 | " %d %d %d %d ", pid, ppid, pgid, sid); |
| 99 | DOCHECK(); | |
| 4643740a | 100 | if ((p->p_flags & P_CONTROLT) && (tp = sess->s_ttyp)) |
| f8c7a42d | 101 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 984263bc MD |
102 | "%d,%d ", major(tp->t_dev), minor(tp->t_dev)); |
| 103 | else | |
| f8c7a42d | 104 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 984263bc MD |
105 | "%d,%d ", -1, -1); |
| 106 | DOCHECK(); | |
| 107 | ||
| 108 | sep = ""; | |
| 109 | if (sess->s_ttyvp) { | |
| f8c7a42d | 110 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "%sctty", sep); |
| 984263bc MD |
111 | sep = ","; |
| 112 | DOCHECK(); | |
| 113 | } | |
| 114 | if (SESS_LEADER(p)) { | |
| f8c7a42d | 115 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "%ssldr", sep); |
| 984263bc MD |
116 | sep = ","; |
| 117 | DOCHECK(); | |
| 118 | } | |
| 119 | if (*sep != ',') { | |
| f8c7a42d | 120 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "noflags"); |
| 984263bc MD |
121 | DOCHECK(); |
| 122 | } | |
| 123 | ||
| 4643740a | 124 | if (p->p_flags & P_SWAPPEDOUT) { |
| f8c7a42d | 125 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 344ad853 MD |
126 | " -1,-1 -1,-1 -1,-1"); |
| 127 | } else { | |
| fde7ac71 | 128 | struct rusage ru; |
| 984263bc | 129 | |
| fde7ac71 | 130 | calcru_proc(p, &ru); |
| f8c7a42d | 131 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 984263bc | 132 | " %ld,%ld %ld,%ld %ld,%ld", |
| d9fa5f67 SS |
133 | p->p_start.tv_sec, |
| 134 | p->p_start.tv_usec, | |
| fde7ac71 SS |
135 | ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, |
| 136 | ru.ru_stime.tv_sec, ru.ru_stime.tv_usec); | |
| 344ad853 | 137 | } |
| 984263bc MD |
138 | DOCHECK(); |
| 139 | ||
| f8c7a42d | 140 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, " %s", |
| 08f2f1bb | 141 | (lp->lwp_wchan && lp->lwp_wmesg) ? lp->lwp_wmesg : "nochan"); |
| 984263bc MD |
142 | DOCHECK(); |
| 143 | ||
| 144 | cr = p->p_ucred; | |
| 145 | ||
| f8c7a42d | 146 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, " %lu %lu %lu", |
| 984263bc | 147 | (u_long)cr->cr_uid, |
| 41c20dac MD |
148 | (u_long)p->p_ucred->cr_ruid, |
| 149 | (u_long)p->p_ucred->cr_rgid); | |
| 984263bc MD |
150 | DOCHECK(); |
| 151 | ||
| 41c20dac | 152 | /* egid (p->p_ucred->cr_svgid) is equal to cr_ngroups[0] |
| 984263bc MD |
153 | see also getegid(2) in /sys/kern/kern_prot.c */ |
| 154 | ||
| 155 | for (i = 0; i < cr->cr_ngroups; i++) { | |
| f8c7a42d | 156 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 984263bc MD |
157 | ",%lu", (u_long)cr->cr_groups[i]); |
| 158 | DOCHECK(); | |
| 159 | } | |
| 160 | ||
| 41c20dac | 161 | if (p->p_ucred->cr_prison) |
| f8c7a42d | 162 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
| 41c20dac | 163 | " %s", p->p_ucred->cr_prison->pr_host); |
| 984263bc | 164 | else |
| f8c7a42d | 165 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, " -"); |
| 984263bc | 166 | DOCHECK(); |
| f8c7a42d | 167 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "\n"); |
| 984263bc MD |
168 | DOCHECK(); |
| 169 | ||
| 170 | xlen = ps - psbuf; | |
| e54488bb | 171 | xlen -= (size_t)uio->uio_offset; |
| 984263bc | 172 | ps = psbuf + uio->uio_offset; |
| e54488bb MD |
173 | xlen = szmin(xlen, uio->uio_resid); |
| 174 | if (xlen == 0) | |
| 984263bc MD |
175 | error = 0; |
| 176 | else | |
| aa0a27c8 | 177 | error = uiomove_frombuf(ps, xlen, uio); |
| 984263bc MD |
178 | |
| 179 | return (error); | |
| 180 | ||
| 181 | bailout: | |
| 182 | return (ENOMEM); | |
| 183 | } | |
| 184 | ||
| 185 | int | |
| c7e98b2f | 186 | procfs_docmdline(struct proc *curp, struct lwp *lp, struct pfsnode *pfs, |
| ac424f9b | 187 | struct uio *uio) |
| 984263bc | 188 | { |
| c7e98b2f | 189 | struct proc *p = lp->lwp_proc; |
| 984263bc | 190 | char *ps; |
| 984263bc MD |
191 | int error; |
| 192 | char *buf, *bp; | |
| 984263bc | 193 | struct ps_strings pstr; |
| d80771bb | 194 | char **ps_argvstr; |
| 984263bc MD |
195 | int i; |
| 196 | size_t bytes_left, done; | |
| e54488bb | 197 | size_t buflen, xlen; |
| 984263bc MD |
198 | |
| 199 | if (uio->uio_rw != UIO_READ) | |
| 200 | return (EOPNOTSUPP); | |
| 201 | ||
| 202 | /* | |
| 203 | * If we are using the ps/cmdline caching, use that. Otherwise | |
| 204 | * revert back to the old way which only implements full cmdline | |
| 205 | * for the currept process and just p->p_comm for all other | |
| 206 | * processes. | |
| 207 | * Note that if the argv is no longer available, we deliberately | |
| 208 | * don't fall back on p->p_comm or return an error: the authentic | |
| 209 | * Linux behaviour is to return zero-length in this case. | |
| 210 | */ | |
| 211 | ||
| 212 | if (p->p_args && | |
| 213 | (ps_argsopen || (CHECKIO(curp, p) && | |
| 4643740a MD |
214 | (p->p_flags & P_INEXEC) == 0 && |
| 215 | !p_trespass(curp->p_ucred, p->p_ucred))) | |
| 41c20dac | 216 | ) { |
| 984263bc MD |
217 | bp = p->p_args->ar_args; |
| 218 | buflen = p->p_args->ar_length; | |
| 219 | buf = 0; | |
| 220 | } else if (p != curp) { | |
| 221 | bp = p->p_comm; | |
| 222 | buflen = MAXCOMLEN; | |
| 223 | buf = 0; | |
| 224 | } else { | |
| 225 | buflen = 256; | |
| 226 | MALLOC(buf, char *, buflen + 1, M_TEMP, M_WAITOK); | |
| 227 | bp = buf; | |
| 228 | ps = buf; | |
| 229 | error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr)); | |
| 230 | if (error) { | |
| 231 | FREE(buf, M_TEMP); | |
| 232 | return (error); | |
| 233 | } | |
| d80771bb JS |
234 | if (pstr.ps_nargvstr > ARG_MAX) { |
| 235 | FREE(buf, M_TEMP); | |
| 236 | return (E2BIG); | |
| 237 | } | |
| 238 | MALLOC(ps_argvstr, char **, pstr.ps_nargvstr * sizeof(char *), | |
| 239 | M_TEMP, M_WAITOK); | |
| 240 | error = copyin((void *)pstr.ps_argvstr, ps_argvstr, | |
| 241 | pstr.ps_nargvstr * sizeof(char *)); | |
| 242 | if (error) { | |
| 243 | FREE(ps_argvstr, M_TEMP); | |
| 244 | FREE(buf, M_TEMP); | |
| 245 | return (error); | |
| 246 | } | |
| 984263bc MD |
247 | bytes_left = buflen; |
| 248 | for (i = 0; bytes_left && (i < pstr.ps_nargvstr); i++) { | |
| d80771bb | 249 | error = copyinstr(ps_argvstr[i], ps, |
| 984263bc MD |
250 | bytes_left, &done); |
| 251 | /* If too long or malformed, just truncate */ | |
| 252 | if (error) { | |
| 253 | error = 0; | |
| 254 | break; | |
| 255 | } | |
| 256 | ps += done; | |
| 257 | bytes_left -= done; | |
| 258 | } | |
| 259 | buflen = ps - buf; | |
| d80771bb | 260 | FREE(ps_argvstr, M_TEMP); |
| 984263bc MD |
261 | } |
| 262 | ||
| e54488bb MD |
263 | buflen -= (size_t)uio->uio_offset; |
| 264 | ps = bp + (size_t)uio->uio_offset; | |
| 265 | xlen = szmin(buflen, uio->uio_resid); | |
| 266 | if (xlen == 0) | |
| 984263bc MD |
267 | error = 0; |
| 268 | else | |
| 25e80b06 | 269 | error = uiomove_frombuf(bp, buflen, uio); |
| 984263bc MD |
270 | if (buf) |
| 271 | FREE(buf, M_TEMP); | |
| 272 | return (error); | |
| 273 | } |