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> | |
48 | #include <sys/jail.h> | |
49 | #include <sys/vnode.h> | |
50 | #include <sys/tty.h> | |
51 | #include <sys/resourcevar.h> | |
1f2de5d4 | 52 | #include <vfs/procfs/procfs.h> |
984263bc MD |
53 | |
54 | #include <vm/vm.h> | |
55 | #include <vm/pmap.h> | |
56 | #include <vm/vm_param.h> | |
57 | #include <sys/exec.h> | |
58 | ||
59 | #define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0) | |
60 | int | |
c7e98b2f | 61 | procfs_dostatus(struct proc *curp, struct lwp *lp, struct pfsnode *pfs, |
ac424f9b | 62 | struct uio *uio) |
984263bc | 63 | { |
c7e98b2f | 64 | struct proc *p = lp->lwp_proc; |
984263bc MD |
65 | struct session *sess; |
66 | struct tty *tp; | |
67 | struct ucred *cr; | |
68 | char *ps; | |
69 | char *sep; | |
70 | int pid, ppid, pgid, sid; | |
71 | int i; | |
72 | int xlen; | |
73 | int error; | |
74 | char psbuf[256]; /* XXX - conservative */ | |
75 | ||
76 | if (uio->uio_rw != UIO_READ) | |
77 | return (EOPNOTSUPP); | |
78 | ||
79 | pid = p->p_pid; | |
80 | ppid = p->p_pptr ? p->p_pptr->p_pid : 0; | |
81 | pgid = p->p_pgrp->pg_id; | |
82 | sess = p->p_pgrp->pg_session; | |
83 | sid = sess->s_leader ? sess->s_leader->p_pid : 0; | |
84 | ||
85 | /* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg | |
86 | euid ruid rgid,egid,groups[1 .. NGROUPS] | |
87 | */ | |
88 | KASSERT(sizeof(psbuf) > MAXCOMLEN, | |
89 | ("Too short buffer for new MAXCOMLEN")); | |
90 | ||
91 | ps = psbuf; | |
92 | bcopy(p->p_comm, ps, MAXCOMLEN); | |
93 | ps[MAXCOMLEN] = '\0'; | |
94 | ps += strlen(ps); | |
95 | DOCHECK(); | |
f8c7a42d | 96 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
984263bc MD |
97 | " %d %d %d %d ", pid, ppid, pgid, sid); |
98 | DOCHECK(); | |
99 | if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp)) | |
f8c7a42d | 100 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
984263bc MD |
101 | "%d,%d ", major(tp->t_dev), minor(tp->t_dev)); |
102 | else | |
f8c7a42d | 103 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
984263bc MD |
104 | "%d,%d ", -1, -1); |
105 | DOCHECK(); | |
106 | ||
107 | sep = ""; | |
108 | if (sess->s_ttyvp) { | |
f8c7a42d | 109 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "%sctty", sep); |
984263bc MD |
110 | sep = ","; |
111 | DOCHECK(); | |
112 | } | |
113 | if (SESS_LEADER(p)) { | |
f8c7a42d | 114 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "%ssldr", sep); |
984263bc MD |
115 | sep = ","; |
116 | DOCHECK(); | |
117 | } | |
118 | if (*sep != ',') { | |
f8c7a42d | 119 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "noflags"); |
984263bc MD |
120 | DOCHECK(); |
121 | } | |
122 | ||
344ad853 | 123 | if (p->p_flag & P_SWAPPEDOUT) { |
f8c7a42d | 124 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
344ad853 MD |
125 | " -1,-1 -1,-1 -1,-1"); |
126 | } else { | |
fde7ac71 | 127 | struct rusage ru; |
984263bc | 128 | |
fde7ac71 | 129 | calcru_proc(p, &ru); |
f8c7a42d | 130 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
984263bc | 131 | " %ld,%ld %ld,%ld %ld,%ld", |
d9fa5f67 SS |
132 | p->p_start.tv_sec, |
133 | p->p_start.tv_usec, | |
fde7ac71 SS |
134 | ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, |
135 | ru.ru_stime.tv_sec, ru.ru_stime.tv_usec); | |
344ad853 | 136 | } |
984263bc MD |
137 | DOCHECK(); |
138 | ||
f8c7a42d | 139 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, " %s", |
08f2f1bb | 140 | (lp->lwp_wchan && lp->lwp_wmesg) ? lp->lwp_wmesg : "nochan"); |
984263bc MD |
141 | DOCHECK(); |
142 | ||
143 | cr = p->p_ucred; | |
144 | ||
f8c7a42d | 145 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, " %lu %lu %lu", |
984263bc | 146 | (u_long)cr->cr_uid, |
41c20dac MD |
147 | (u_long)p->p_ucred->cr_ruid, |
148 | (u_long)p->p_ucred->cr_rgid); | |
984263bc MD |
149 | DOCHECK(); |
150 | ||
41c20dac | 151 | /* egid (p->p_ucred->cr_svgid) is equal to cr_ngroups[0] |
984263bc MD |
152 | see also getegid(2) in /sys/kern/kern_prot.c */ |
153 | ||
154 | for (i = 0; i < cr->cr_ngroups; i++) { | |
f8c7a42d | 155 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
984263bc MD |
156 | ",%lu", (u_long)cr->cr_groups[i]); |
157 | DOCHECK(); | |
158 | } | |
159 | ||
41c20dac | 160 | if (p->p_ucred->cr_prison) |
f8c7a42d | 161 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, |
41c20dac | 162 | " %s", p->p_ucred->cr_prison->pr_host); |
984263bc | 163 | else |
f8c7a42d | 164 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, " -"); |
984263bc | 165 | DOCHECK(); |
f8c7a42d | 166 | ps += ksnprintf(ps, psbuf + sizeof(psbuf) - ps, "\n"); |
984263bc MD |
167 | DOCHECK(); |
168 | ||
169 | xlen = ps - psbuf; | |
170 | xlen -= uio->uio_offset; | |
171 | ps = psbuf + uio->uio_offset; | |
172 | xlen = imin(xlen, uio->uio_resid); | |
173 | if (xlen <= 0) | |
174 | error = 0; | |
175 | else | |
aa0a27c8 | 176 | error = uiomove_frombuf(ps, xlen, uio); |
984263bc MD |
177 | |
178 | return (error); | |
179 | ||
180 | bailout: | |
181 | return (ENOMEM); | |
182 | } | |
183 | ||
184 | int | |
c7e98b2f | 185 | procfs_docmdline(struct proc *curp, struct lwp *lp, struct pfsnode *pfs, |
ac424f9b | 186 | struct uio *uio) |
984263bc | 187 | { |
c7e98b2f | 188 | struct proc *p = lp->lwp_proc; |
984263bc MD |
189 | char *ps; |
190 | int xlen; | |
191 | int error; | |
192 | char *buf, *bp; | |
193 | int buflen; | |
194 | struct ps_strings pstr; | |
d80771bb | 195 | char **ps_argvstr; |
984263bc MD |
196 | int i; |
197 | size_t bytes_left, done; | |
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) && | |
41c20dac MD |
214 | (p->p_flag & P_INEXEC) == 0 && !p_trespass(curp->p_ucred, p->p_ucred))) |
215 | ) { | |
984263bc MD |
216 | bp = p->p_args->ar_args; |
217 | buflen = p->p_args->ar_length; | |
218 | buf = 0; | |
219 | } else if (p != curp) { | |
220 | bp = p->p_comm; | |
221 | buflen = MAXCOMLEN; | |
222 | buf = 0; | |
223 | } else { | |
224 | buflen = 256; | |
225 | MALLOC(buf, char *, buflen + 1, M_TEMP, M_WAITOK); | |
226 | bp = buf; | |
227 | ps = buf; | |
228 | error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr)); | |
229 | if (error) { | |
230 | FREE(buf, M_TEMP); | |
231 | return (error); | |
232 | } | |
d80771bb JS |
233 | if (pstr.ps_nargvstr > ARG_MAX) { |
234 | FREE(buf, M_TEMP); | |
235 | return (E2BIG); | |
236 | } | |
237 | MALLOC(ps_argvstr, char **, pstr.ps_nargvstr * sizeof(char *), | |
238 | M_TEMP, M_WAITOK); | |
239 | error = copyin((void *)pstr.ps_argvstr, ps_argvstr, | |
240 | pstr.ps_nargvstr * sizeof(char *)); | |
241 | if (error) { | |
242 | FREE(ps_argvstr, M_TEMP); | |
243 | FREE(buf, M_TEMP); | |
244 | return (error); | |
245 | } | |
984263bc MD |
246 | bytes_left = buflen; |
247 | for (i = 0; bytes_left && (i < pstr.ps_nargvstr); i++) { | |
d80771bb | 248 | error = copyinstr(ps_argvstr[i], ps, |
984263bc MD |
249 | bytes_left, &done); |
250 | /* If too long or malformed, just truncate */ | |
251 | if (error) { | |
252 | error = 0; | |
253 | break; | |
254 | } | |
255 | ps += done; | |
256 | bytes_left -= done; | |
257 | } | |
258 | buflen = ps - buf; | |
d80771bb | 259 | FREE(ps_argvstr, M_TEMP); |
984263bc MD |
260 | } |
261 | ||
262 | buflen -= uio->uio_offset; | |
263 | ps = bp + uio->uio_offset; | |
264 | xlen = min(buflen, uio->uio_resid); | |
265 | if (xlen <= 0) | |
266 | error = 0; | |
267 | else | |
25e80b06 | 268 | error = uiomove_frombuf(bp, buflen, uio); |
984263bc MD |
269 | if (buf) |
270 | FREE(buf, M_TEMP); | |
271 | return (error); | |
272 | } |