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(¬elst); 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(¬elst); 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, ¶ms); 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, ¶ms); 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)(¶ms, seginfo.count, hdr, hdrsize, ¬elst, 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, ¶ms, 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)(¶ms, seginfo.count, hdr, hdrsize, ¬elst, 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, ¶ms, 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(¬elst)) != NULL) { 1469 TAILQ_REMOVE(¬elst, 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(¬elst)) != NULL) { 1453 TAILQ_REMOVE(¬elst, 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 --- |