imgact_elf.c (8a36da99deb0e19363ec04e4d3facd869c1028f5) imgact_elf.c (78f57a9cdef729f94669fe1eb494666f403f9235)
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2017 Dell EMC
5 * Copyright (c) 2000 David O'Brien
6 * Copyright (c) 1995-1996 Søren Schmidt
7 * Copyright (c) 1996 Peter Wemm
8 * All rights reserved.

--- 22 unchanged lines hidden (view full) ---

31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include "opt_capsicum.h"
38#include "opt_compat.h"
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2017 Dell EMC
5 * Copyright (c) 2000 David O'Brien
6 * Copyright (c) 1995-1996 Søren Schmidt
7 * Copyright (c) 1996 Peter Wemm
8 * All rights reserved.

--- 22 unchanged lines hidden (view full) ---

31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include "opt_capsicum.h"
38#include "opt_compat.h"
39#include "opt_gzio.h"
40
41#include <sys/param.h>
42#include <sys/capsicum.h>
39
40#include <sys/param.h>
41#include <sys/capsicum.h>
42#include <sys/compressor.h>
43#include <sys/exec.h>
44#include <sys/fcntl.h>
43#include <sys/exec.h>
44#include <sys/fcntl.h>
45#include <sys/gzio.h>
46#include <sys/imgact.h>
47#include <sys/imgact_elf.h>
48#include <sys/jail.h>
49#include <sys/kernel.h>
50#include <sys/lock.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/mman.h>

--- 1126 unchanged lines hidden (view full) ---

1180
1181/* Coredump output parameters. */
1182struct coredump_params {
1183 off_t offset;
1184 struct ucred *active_cred;
1185 struct ucred *file_cred;
1186 struct thread *td;
1187 struct vnode *vp;
45#include <sys/imgact.h>
46#include <sys/imgact_elf.h>
47#include <sys/jail.h>
48#include <sys/kernel.h>
49#include <sys/lock.h>
50#include <sys/malloc.h>
51#include <sys/mount.h>
52#include <sys/mman.h>

--- 1126 unchanged lines hidden (view full) ---

1179
1180/* Coredump output parameters. */
1181struct coredump_params {
1182 off_t offset;
1183 struct ucred *active_cred;
1184 struct ucred *file_cred;
1185 struct thread *td;
1186 struct vnode *vp;
1188 struct gzio_stream *gzs;
1187 struct compressor *comp;
1189};
1190
1188};
1189
1190extern int compress_user_cores;
1191extern int compress_user_cores_level;
1192
1191static void cb_put_phdr(vm_map_entry_t, void *);
1192static void cb_size_segment(vm_map_entry_t, void *);
1193static int core_write(struct coredump_params *, const void *, size_t, off_t,
1194 enum uio_seg);
1195static void each_dumpable_segment(struct thread *, segment_callback, void *);
1196static int __elfN(corehdr)(struct coredump_params *, int, void *, size_t,
1197 struct note_info_list *, size_t);
1198static void __elfN(prepare_notes)(struct thread *, struct note_info_list *,

--- 15 unchanged lines hidden (view full) ---

1214static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
1215static void note_procstat_files(void *, struct sbuf *, size_t *);
1216static void note_procstat_groups(void *, struct sbuf *, size_t *);
1217static void note_procstat_osrel(void *, struct sbuf *, size_t *);
1218static void note_procstat_rlimit(void *, struct sbuf *, size_t *);
1219static void note_procstat_umask(void *, struct sbuf *, size_t *);
1220static void note_procstat_vmmap(void *, struct sbuf *, size_t *);
1221
1193static void cb_put_phdr(vm_map_entry_t, void *);
1194static void cb_size_segment(vm_map_entry_t, void *);
1195static int core_write(struct coredump_params *, const void *, size_t, off_t,
1196 enum uio_seg);
1197static void each_dumpable_segment(struct thread *, segment_callback, void *);
1198static int __elfN(corehdr)(struct coredump_params *, int, void *, size_t,
1199 struct note_info_list *, size_t);
1200static void __elfN(prepare_notes)(struct thread *, struct note_info_list *,

--- 15 unchanged lines hidden (view full) ---

1216static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
1217static void note_procstat_files(void *, struct sbuf *, size_t *);
1218static void note_procstat_groups(void *, struct sbuf *, size_t *);
1219static void note_procstat_osrel(void *, struct sbuf *, size_t *);
1220static void note_procstat_rlimit(void *, struct sbuf *, size_t *);
1221static void note_procstat_umask(void *, struct sbuf *, size_t *);
1222static void note_procstat_vmmap(void *, struct sbuf *, size_t *);
1223
1222#ifdef GZIO
1223extern int compress_user_cores_gzlevel;
1224
1225/*
1226 * Write out a core segment to the compression stream.
1227 */
1228static int
1229compress_chunk(struct coredump_params *p, char *base, char *buf, u_int len)
1230{
1231 u_int chunk_len;
1232 int error;
1233
1234 while (len > 0) {
1235 chunk_len = MIN(len, CORE_BUF_SIZE);
1236
1237 /*
1238 * We can get EFAULT error here.
1239 * In that case zero out the current chunk of the segment.
1240 */
1241 error = copyin(base, buf, chunk_len);
1242 if (error != 0)
1243 bzero(buf, chunk_len);
1224/*
1225 * Write out a core segment to the compression stream.
1226 */
1227static int
1228compress_chunk(struct coredump_params *p, char *base, char *buf, u_int len)
1229{
1230 u_int chunk_len;
1231 int error;
1232
1233 while (len > 0) {
1234 chunk_len = MIN(len, CORE_BUF_SIZE);
1235
1236 /*
1237 * We can get EFAULT error here.
1238 * In that case zero out the current chunk of the segment.
1239 */
1240 error = copyin(base, buf, chunk_len);
1241 if (error != 0)
1242 bzero(buf, chunk_len);
1244 error = gzio_write(p->gzs, buf, chunk_len);
1243 error = compressor_write(p->comp, buf, chunk_len);
1245 if (error != 0)
1246 break;
1247 base += chunk_len;
1248 len -= chunk_len;
1249 }
1250 return (error);
1251}
1252
1253static int
1244 if (error != 0)
1245 break;
1246 base += chunk_len;
1247 len -= chunk_len;
1248 }
1249 return (error);
1250}
1251
1252static int
1254core_gz_write(void *base, size_t len, off_t offset, void *arg)
1253core_compressed_write(void *base, size_t len, off_t offset, void *arg)
1255{
1256
1257 return (core_write((struct coredump_params *)arg, base, len, offset,
1258 UIO_SYSSPACE));
1259}
1254{
1255
1256 return (core_write((struct coredump_params *)arg, base, len, offset,
1257 UIO_SYSSPACE));
1258}
1260#endif /* GZIO */
1261
1262static int
1263core_write(struct coredump_params *p, const void *base, size_t len,
1264 off_t offset, enum uio_seg seg)
1265{
1266
1267 return (vn_rdwr_inchunks(UIO_WRITE, p->vp, __DECONST(void *, base),
1268 len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED,
1269 p->active_cred, p->file_cred, NULL, p->td));
1270}
1271
1272static int
1273core_output(void *base, size_t len, off_t offset, struct coredump_params *p,
1274 void *tmpbuf)
1275{
1276 int error;
1277
1259
1260static int
1261core_write(struct coredump_params *p, const void *base, size_t len,
1262 off_t offset, enum uio_seg seg)
1263{
1264
1265 return (vn_rdwr_inchunks(UIO_WRITE, p->vp, __DECONST(void *, base),
1266 len, offset, seg, IO_UNIT | IO_DIRECT | IO_RANGELOCKED,
1267 p->active_cred, p->file_cred, NULL, p->td));
1268}
1269
1270static int
1271core_output(void *base, size_t len, off_t offset, struct coredump_params *p,
1272 void *tmpbuf)
1273{
1274 int error;
1275
1278#ifdef GZIO
1279 if (p->gzs != NULL)
1276 if (p->comp != NULL)
1280 return (compress_chunk(p, base, tmpbuf, len));
1277 return (compress_chunk(p, base, tmpbuf, len));
1281#endif
1278
1282 /*
1283 * EFAULT is a non-fatal error that we can get, for example,
1284 * if the segment is backed by a file but extends beyond its
1285 * end.
1286 */
1287 error = core_write(p, base, len, offset, UIO_USERSPACE);
1288 if (error == EFAULT) {
1289 log(LOG_WARNING, "Failed to fully fault in a core file segment "

--- 28 unchanged lines hidden (view full) ---

1318 * non-sleepable lock held is unsafe. The lock is needed for
1319 * those routines when dumping a live process. In our case we
1320 * can safely release the lock before draining and acquire
1321 * again after.
1322 */
1323 locked = PROC_LOCKED(p->td->td_proc);
1324 if (locked)
1325 PROC_UNLOCK(p->td->td_proc);
1279 /*
1280 * EFAULT is a non-fatal error that we can get, for example,
1281 * if the segment is backed by a file but extends beyond its
1282 * end.
1283 */
1284 error = core_write(p, base, len, offset, UIO_USERSPACE);
1285 if (error == EFAULT) {
1286 log(LOG_WARNING, "Failed to fully fault in a core file segment "

--- 28 unchanged lines hidden (view full) ---

1315 * non-sleepable lock held is unsafe. The lock is needed for
1316 * those routines when dumping a live process. In our case we
1317 * can safely release the lock before draining and acquire
1318 * again after.
1319 */
1320 locked = PROC_LOCKED(p->td->td_proc);
1321 if (locked)
1322 PROC_UNLOCK(p->td->td_proc);
1326#ifdef GZIO
1327 if (p->gzs != NULL)
1328 error = gzio_write(p->gzs, __DECONST(char *, data), len);
1323 if (p->comp != NULL)
1324 error = compressor_write(p->comp, __DECONST(char *, data), len);
1329 else
1325 else
1330#endif
1331 error = core_write(p, __DECONST(void *, data), len, p->offset,
1332 UIO_SYSSPACE);
1333 if (locked)
1334 PROC_LOCK(p->td->td_proc);
1335 if (error != 0)
1336 return (-error);
1337 p->offset += len;
1338 return (len);

--- 18 unchanged lines hidden (view full) ---

1357 struct ucred *cred = td->td_ucred;
1358 int error = 0;
1359 struct sseg_closure seginfo;
1360 struct note_info_list notelst;
1361 struct coredump_params params;
1362 struct note_info *ninfo;
1363 void *hdr, *tmpbuf;
1364 size_t hdrsize, notesz, coresize;
1326 error = core_write(p, __DECONST(void *, data), len, p->offset,
1327 UIO_SYSSPACE);
1328 if (locked)
1329 PROC_LOCK(p->td->td_proc);
1330 if (error != 0)
1331 return (-error);
1332 p->offset += len;
1333 return (len);

--- 18 unchanged lines hidden (view full) ---

1352 struct ucred *cred = td->td_ucred;
1353 int error = 0;
1354 struct sseg_closure seginfo;
1355 struct note_info_list notelst;
1356 struct coredump_params params;
1357 struct note_info *ninfo;
1358 void *hdr, *tmpbuf;
1359 size_t hdrsize, notesz, coresize;
1365#ifdef GZIO
1366 boolean_t compress;
1367
1360
1368 compress = (flags & IMGACT_CORE_COMPRESS) != 0;
1369#endif
1370 hdr = NULL;
1371 tmpbuf = NULL;
1372 TAILQ_INIT(&notelst);
1373
1374 /* Size the program segments. */
1375 seginfo.count = 0;
1376 seginfo.size = 0;
1377 each_dumpable_segment(td, cb_size_segment, &seginfo);

--- 8 unchanged lines hidden (view full) ---

1386 coresize = round_page(hdrsize + notesz) + seginfo.size;
1387
1388 /* Set up core dump parameters. */
1389 params.offset = 0;
1390 params.active_cred = cred;
1391 params.file_cred = NOCRED;
1392 params.td = td;
1393 params.vp = vp;
1361 hdr = NULL;
1362 tmpbuf = NULL;
1363 TAILQ_INIT(&notelst);
1364
1365 /* Size the program segments. */
1366 seginfo.count = 0;
1367 seginfo.size = 0;
1368 each_dumpable_segment(td, cb_size_segment, &seginfo);

--- 8 unchanged lines hidden (view full) ---

1377 coresize = round_page(hdrsize + notesz) + seginfo.size;
1378
1379 /* Set up core dump parameters. */
1380 params.offset = 0;
1381 params.active_cred = cred;
1382 params.file_cred = NOCRED;
1383 params.td = td;
1384 params.vp = vp;
1394 params.gzs = NULL;
1385 params.comp = NULL;
1395
1396#ifdef RACCT
1397 if (racct_enable) {
1398 PROC_LOCK(td->td_proc);
1399 error = racct_add(td->td_proc, RACCT_CORE, coresize);
1400 PROC_UNLOCK(td->td_proc);
1401 if (error != 0) {
1402 error = EFAULT;
1403 goto done;
1404 }
1405 }
1406#endif
1407 if (coresize >= limit) {
1408 error = EFAULT;
1409 goto done;
1410 }
1411
1386
1387#ifdef RACCT
1388 if (racct_enable) {
1389 PROC_LOCK(td->td_proc);
1390 error = racct_add(td->td_proc, RACCT_CORE, coresize);
1391 PROC_UNLOCK(td->td_proc);
1392 if (error != 0) {
1393 error = EFAULT;
1394 goto done;
1395 }
1396 }
1397#endif
1398 if (coresize >= limit) {
1399 error = EFAULT;
1400 goto done;
1401 }
1402
1412#ifdef GZIO
1413 /* Create a compression stream if necessary. */
1403 /* Create a compression stream if necessary. */
1414 if (compress) {
1415 params.gzs = gzio_init(core_gz_write, GZIO_DEFLATE,
1416 CORE_BUF_SIZE, compress_user_cores_gzlevel, &params);
1417 if (params.gzs == NULL) {
1404 if (compress_user_cores != 0) {
1405 params.comp = compressor_init(core_compressed_write,
1406 compress_user_cores, CORE_BUF_SIZE,
1407 compress_user_cores_level, &params);
1408 if (params.comp == NULL) {
1418 error = EFAULT;
1419 goto done;
1420 }
1421 tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO);
1422 }
1409 error = EFAULT;
1410 goto done;
1411 }
1412 tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO);
1413 }
1423#endif
1424
1425 /*
1426 * Allocate memory for building the header, fill it up,
1427 * and write it out following the notes.
1428 */
1429 hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
1430 error = __elfN(corehdr)(&params, seginfo.count, hdr, hdrsize, &notelst,
1431 notesz);

--- 9 unchanged lines hidden (view full) ---

1441 for (i = 0; i < seginfo.count; i++) {
1442 error = core_output((caddr_t)(uintptr_t)php->p_vaddr,
1443 php->p_filesz, offset, &params, tmpbuf);
1444 if (error != 0)
1445 break;
1446 offset += php->p_filesz;
1447 php++;
1448 }
1414
1415 /*
1416 * Allocate memory for building the header, fill it up,
1417 * and write it out following the notes.
1418 */
1419 hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
1420 error = __elfN(corehdr)(&params, seginfo.count, hdr, hdrsize, &notelst,
1421 notesz);

--- 9 unchanged lines hidden (view full) ---

1431 for (i = 0; i < seginfo.count; i++) {
1432 error = core_output((caddr_t)(uintptr_t)php->p_vaddr,
1433 php->p_filesz, offset, &params, tmpbuf);
1434 if (error != 0)
1435 break;
1436 offset += php->p_filesz;
1437 php++;
1438 }
1449#ifdef GZIO
1450 if (error == 0 && compress)
1451 error = gzio_flush(params.gzs);
1452#endif
1439 if (error == 0 && params.comp != NULL)
1440 error = compressor_flush(params.comp);
1453 }
1454 if (error) {
1455 log(LOG_WARNING,
1456 "Failed to write core file for process %s (error %d)\n",
1457 curproc->p_comm, error);
1458 }
1459
1460done:
1441 }
1442 if (error) {
1443 log(LOG_WARNING,
1444 "Failed to write core file for process %s (error %d)\n",
1445 curproc->p_comm, error);
1446 }
1447
1448done:
1461#ifdef GZIO
1462 if (compress) {
1463 free(tmpbuf, M_TEMP);
1464 if (params.gzs != NULL)
1465 gzio_fini(params.gzs);
1466 }
1467#endif
1449 free(tmpbuf, M_TEMP);
1450 if (params.comp != NULL)
1451 compressor_fini(params.comp);
1468 while ((ninfo = TAILQ_FIRST(&notelst)) != NULL) {
1469 TAILQ_REMOVE(&notelst, ninfo, link);
1470 free(ninfo, M_TEMP);
1471 }
1472 if (hdr != NULL)
1473 free(hdr, M_TEMP);
1474
1475 return (error);

--- 1008 unchanged lines hidden ---
1452 while ((ninfo = TAILQ_FIRST(&notelst)) != NULL) {
1453 TAILQ_REMOVE(&notelst, ninfo, link);
1454 free(ninfo, M_TEMP);
1455 }
1456 if (hdr != NULL)
1457 free(hdr, M_TEMP);
1458
1459 return (error);

--- 1008 unchanged lines hidden ---