Skip to content

Commit d29eb5f

Browse files
committed
Merge patch series "pidfds: add coredump_code field to pidfd_info"
Emanuele Rocca <emanuele.rocca@arm.com> says: This patchs series adds a new field called coredump_code to struct pidfd_info, as well as the relevant selftests. Note that the coredump selftests are currently not passing. * patches from https://patch.msgid.link/acE5fYOgyVUYahIn@NH27D9T0LF: selftests: check pidfd_info->coredump_code correctness pidfds: add coredump_code field to pidfd_info Link: https://patch.msgid.link/acE5fYOgyVUYahIn@NH27D9T0LF Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 3fc66a1 + 7aaa491 commit d29eb5f

7 files changed

Lines changed: 78 additions & 6 deletions

File tree

fs/pidfs.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct pidfs_attr {
5757
};
5858
__u32 coredump_mask;
5959
__u32 coredump_signal;
60+
__u32 coredump_code;
6061
};
6162

6263
static struct rhashtable pidfs_ino_ht;
@@ -333,7 +334,8 @@ static __u32 pidfs_coredump_mask(unsigned long mm_flags)
333334
PIDFD_INFO_EXIT | \
334335
PIDFD_INFO_COREDUMP | \
335336
PIDFD_INFO_SUPPORTED_MASK | \
336-
PIDFD_INFO_COREDUMP_SIGNAL)
337+
PIDFD_INFO_COREDUMP_SIGNAL | \
338+
PIDFD_INFO_COREDUMP_CODE)
337339

338340
static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
339341
{
@@ -347,7 +349,7 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
347349
const struct cred *c;
348350
__u64 mask;
349351

350-
BUILD_BUG_ON(sizeof(struct pidfd_info) != PIDFD_INFO_SIZE_VER2);
352+
BUILD_BUG_ON(sizeof(struct pidfd_info) != PIDFD_INFO_SIZE_VER3);
351353

352354
if (!uinfo)
353355
return -EINVAL;
@@ -380,9 +382,10 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
380382
if (mask & PIDFD_INFO_COREDUMP) {
381383
if (test_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask)) {
382384
smp_rmb();
383-
kinfo.mask |= PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL;
385+
kinfo.mask |= PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL | PIDFD_INFO_COREDUMP_CODE;
384386
kinfo.coredump_mask = attr->coredump_mask;
385387
kinfo.coredump_signal = attr->coredump_signal;
388+
kinfo.coredump_code = attr->coredump_code;
386389
}
387390
}
388391

@@ -755,8 +758,9 @@ void pidfs_coredump(const struct coredump_params *cprm)
755758
PIDFD_COREDUMPED;
756759
/* If coredumping is set to skip we should never end up here. */
757760
VFS_WARN_ON_ONCE(attr->coredump_mask & PIDFD_COREDUMP_SKIP);
758-
/* Expose the signal number that caused the coredump. */
761+
/* Expose the signal number and code that caused the coredump. */
759762
attr->coredump_signal = cprm->siginfo->si_signo;
763+
attr->coredump_code = cprm->siginfo->si_code;
760764
smp_wmb();
761765
set_bit(PIDFS_ATTR_BIT_COREDUMP, &attr->attr_mask);
762766
}

include/uapi/linux/pidfd.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@
2929
#define PIDFD_INFO_COREDUMP (1UL << 4) /* Only returned if requested. */
3030
#define PIDFD_INFO_SUPPORTED_MASK (1UL << 5) /* Want/got supported mask flags */
3131
#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6) /* Always returned if PIDFD_INFO_COREDUMP is requested. */
32+
#define PIDFD_INFO_COREDUMP_CODE (1UL << 7) /* Always returned if PIDFD_INFO_COREDUMP is requested. */
3233

3334
#define PIDFD_INFO_SIZE_VER0 64 /* sizeof first published struct */
3435
#define PIDFD_INFO_SIZE_VER1 72 /* sizeof second published struct */
3536
#define PIDFD_INFO_SIZE_VER2 80 /* sizeof third published struct */
37+
#define PIDFD_INFO_SIZE_VER3 88 /* sizeof fourth published struct */
3638

3739
/*
3840
* Values for @coredump_mask in pidfd_info.
@@ -99,6 +101,8 @@ struct pidfd_info {
99101
struct /* coredump info */ {
100102
__u32 coredump_mask;
101103
__u32 coredump_signal;
104+
__u32 coredump_code;
105+
__u32 coredump_pad; /* align supported_mask to 8 bytes */
102106
};
103107
__u64 supported_mask; /* Mask flags that this kernel supports */
104108
};

tools/testing/selftests/coredump/coredump_socket_protocol_test.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ TEST_F(coredump, socket_request_invalid_size_large)
10041004
*
10051005
* Verify that when using socket-based coredump protocol,
10061006
* the coredump_signal field is correctly exposed as SIGSEGV.
1007+
* Also check that the coredump_code field is correctly exposed
1008+
* as SEGV_MAPERR.
10071009
*/
10081010
TEST_F(coredump, socket_coredump_signal_sigsegv)
10091011
{
@@ -1079,6 +1081,18 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
10791081
goto out;
10801082
}
10811083

1084+
/* Verify coredump_code is available and correct */
1085+
if (!(info.mask & PIDFD_INFO_COREDUMP_CODE)) {
1086+
fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP_CODE not set in mask\n");
1087+
goto out;
1088+
}
1089+
1090+
if (info.coredump_code != SEGV_MAPERR) {
1091+
fprintf(stderr, "socket_coredump_signal_sigsegv: coredump_code=%d, expected SEGV_MAPERR=%d\n",
1092+
info.coredump_code, SEGV_MAPERR);
1093+
goto out;
1094+
}
1095+
10821096
if (!read_coredump_req(fd_coredump, &req)) {
10831097
fprintf(stderr, "socket_coredump_signal_sigsegv: read_coredump_req failed\n");
10841098
goto out;
@@ -1128,6 +1142,8 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
11281142
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP));
11291143
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL));
11301144
ASSERT_EQ(info.coredump_signal, SIGSEGV);
1145+
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_CODE));
1146+
ASSERT_EQ(info.coredump_code, SEGV_MAPERR);
11311147

11321148
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
11331149
}
@@ -1137,6 +1153,8 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
11371153
*
11381154
* Verify that when using socket-based coredump protocol,
11391155
* the coredump_signal field is correctly exposed as SIGABRT.
1156+
* Also check that the coredump_code field is correctly exposed
1157+
* as SI_TKILL.
11401158
*/
11411159
TEST_F(coredump, socket_coredump_signal_sigabrt)
11421160
{
@@ -1212,6 +1230,12 @@ TEST_F(coredump, socket_coredump_signal_sigabrt)
12121230
goto out;
12131231
}
12141232

1233+
if (info.coredump_code != SI_TKILL) {
1234+
fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_code=%d, expected SI_TKILL=%d\n",
1235+
info.coredump_code, SI_TKILL);
1236+
goto out;
1237+
}
1238+
12151239
if (!read_coredump_req(fd_coredump, &req)) {
12161240
fprintf(stderr, "socket_coredump_signal_sigabrt: read_coredump_req failed\n");
12171241
goto out;
@@ -1261,6 +1285,8 @@ TEST_F(coredump, socket_coredump_signal_sigabrt)
12611285
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP));
12621286
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL));
12631287
ASSERT_EQ(info.coredump_signal, SIGABRT);
1288+
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_CODE));
1289+
ASSERT_EQ(info.coredump_code, SI_TKILL);
12641290

12651291
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
12661292
}

tools/testing/selftests/coredump/coredump_socket_test.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ TEST_F(coredump, socket_no_listener)
435435
*
436436
* Verify that when using simple socket-based coredump (@ pattern),
437437
* the coredump_signal field is correctly exposed as SIGSEGV.
438+
* Also check that the coredump_code field is correctly exposed
439+
* as SEGV_MAPERR.
438440
*/
439441
TEST_F(coredump, socket_coredump_signal_sigsegv)
440442
{
@@ -509,6 +511,18 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
509511
goto out;
510512
}
511513

514+
/* Verify coredump_code is available and correct */
515+
if (!(info.mask & PIDFD_INFO_COREDUMP_CODE)) {
516+
fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP_CODE not set in mask\n");
517+
goto out;
518+
}
519+
520+
if (info.coredump_code != SEGV_MAPERR) {
521+
fprintf(stderr, "socket_coredump_signal_sigsegv: coredump_code=%d, expected SEGV_MAPERR=%d\n",
522+
info.coredump_code, SEGV_MAPERR);
523+
goto out;
524+
}
525+
512526
fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached);
513527
if (fd_core_file < 0) {
514528
fprintf(stderr, "socket_coredump_signal_sigsegv: open_coredump_tmpfile failed: %m\n");
@@ -572,6 +586,8 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
572586
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP));
573587
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL));
574588
ASSERT_EQ(info.coredump_signal, SIGSEGV);
589+
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_CODE));
590+
ASSERT_EQ(info.coredump_code, SEGV_MAPERR);
575591

576592
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
577593
}
@@ -581,6 +597,8 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
581597
*
582598
* Verify that when using simple socket-based coredump (@ pattern),
583599
* the coredump_signal field is correctly exposed as SIGABRT.
600+
* Also check that the coredump_code field is correctly exposed
601+
* as SI_TKILL.
584602
*/
585603
TEST_F(coredump, socket_coredump_signal_sigabrt)
586604
{
@@ -655,6 +673,18 @@ TEST_F(coredump, socket_coredump_signal_sigabrt)
655673
goto out;
656674
}
657675

676+
/* Verify coredump_code is available and correct */
677+
if (!(info.mask & PIDFD_INFO_COREDUMP_CODE)) {
678+
fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP_CODE not set in mask\n");
679+
goto out;
680+
}
681+
682+
if (info.coredump_code != SI_TKILL) {
683+
fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_code=%d, expected SI_TKILL=%d\n",
684+
info.coredump_code, SI_TKILL);
685+
goto out;
686+
}
687+
658688
fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached);
659689
if (fd_core_file < 0) {
660690
fprintf(stderr, "socket_coredump_signal_sigabrt: open_coredump_tmpfile failed: %m\n");
@@ -718,6 +748,8 @@ TEST_F(coredump, socket_coredump_signal_sigabrt)
718748
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP));
719749
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL));
720750
ASSERT_EQ(info.coredump_signal, SIGABRT);
751+
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_CODE));
752+
ASSERT_EQ(info.coredump_code, SI_TKILL);
721753

722754
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
723755
}

tools/testing/selftests/coredump/coredump_test_helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info)
148148
fprintf(stderr, "get_pidfd_info: ioctl(PIDFD_GET_INFO) failed: %m\n");
149149
return false;
150150
}
151-
fprintf(stderr, "get_pidfd_info: mask=0x%llx, coredump_mask=0x%x, coredump_signal=%d\n",
152-
(unsigned long long)info->mask, info->coredump_mask, info->coredump_signal);
151+
fprintf(stderr, "get_pidfd_info: mask=0x%llx, coredump_mask=0x%x, coredump_signal=%d, coredump_code=%d\n",
152+
(unsigned long long)info->mask, info->coredump_mask, info->coredump_signal, info->coredump_code);
153153
return true;
154154
}
155155

tools/testing/selftests/pidfd/pidfd.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@
156156
#define PIDFD_INFO_COREDUMP_SIGNAL (1UL << 6)
157157
#endif
158158

159+
#ifndef PIDFD_INFO_COREDUMP_CODE
160+
#define PIDFD_INFO_COREDUMP_CODE (1UL << 7)
161+
#endif
162+
159163
#ifndef PIDFD_COREDUMPED
160164
#define PIDFD_COREDUMPED (1U << 0) /* Did crash and... */
161165
#endif
@@ -194,6 +198,7 @@ struct pidfd_info {
194198
struct {
195199
__u32 coredump_mask;
196200
__u32 coredump_signal;
201+
__u32 coredump_code;
197202
};
198203
__u64 supported_mask;
199204
};

tools/testing/selftests/pidfd/pidfd_info_test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,7 @@ TEST(supported_mask_field)
724724
ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP));
725725
ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_SUPPORTED_MASK));
726726
ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP_SIGNAL));
727+
ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP_CODE));
727728

728729
/* Clean up */
729730
sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);

0 commit comments

Comments
 (0)