diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2020-09-19 08:00:00 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2020-09-19 08:00:00 +0000 |
commit | 42e8d663e3edbb34f9d25fc5801fb85fa4bf8818 (patch) | |
tree | 54469ecf9e78df3825c66b84c49a48d7eb9e5a45 | |
parent | 9282c8a4151f1ad5914ac24eb23d05449ea1cb8c (diff) | |
download | strace-42e8d663e3edbb34f9d25fc5801fb85fa4bf8818.tar.gz |
shmctl: decode struct shm_info argument of SHM_INFO command
* ipc_shmctl.c (struct_shm_info_t): New typedef. Mpersify it.
(print_shm_info): New function.
(SYS_FUNC(shmctl)): Use it to decode struct shm_info argument
of SHM_INFO command.
* tests/ipc_shm.c (print_shm_info): New function.
(main): Use it to check decoding of SHM_INFO command.
* NEWS: Mention this change.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | ipc_shmctl.c | 103 | ||||
-rw-r--r-- | tests/ipc_shm.c | 55 |
3 files changed, 110 insertions, 50 deletions
@@ -9,6 +9,8 @@ Noteworthy changes in release ?.? (????-??-??) and MSG_INFO msgctl syscall commands. * Implemented decoding of struct msqid_ds argument of MSG_STAT and MSG_STAT_ANY msgctl syscall commands. + * Implemented decoding of struct shm_info argument of SHM_INFO + shmctl syscall command. * Implemented decoding of struct shmid_ds argument of SHM_STAT and SHM_STAT_ANY shmctl syscall commands. * Updated lists of BPF_*, CAP_*, FAN_*, IFLA_*, INET_DIAG_REQ_*, diff --git a/ipc_shmctl.c b/ipc_shmctl.c index c4c161ecb..22994e330 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -14,11 +14,13 @@ #include "defs.h" #include DEF_MPERS_TYPE(shmid_ds_t) +#include DEF_MPERS_TYPE(struct_shm_info_t) #include "ipc_defs.h" #include SHM_H_PROVIDER typedef struct NAME_OF_STRUCT_SHMID_DS shmid_ds_t; +typedef struct shm_info struct_shm_info_t; #include MPERS_DEFS @@ -28,46 +30,52 @@ typedef struct NAME_OF_STRUCT_SHMID_DS shmid_ds_t; #define key NAME_OF_STRUCT_IPC_PERM_KEY static void -print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, int cmd) +print_shmid_ds(struct tcb *const tcp, const kernel_ulong_t addr, + const unsigned int cmd) { - /* TODO: We don't properly decode old compat ipc calls. */ - if (cmd & IPC_64) - cmd &= ~IPC_64; shmid_ds_t shmid_ds; - switch (cmd) { - case IPC_SET: - case IPC_STAT: - case SHM_STAT: - case SHM_STAT_ANY: - if (umove_or_printaddr(tcp, addr, &shmid_ds)) - return; - - PRINT_FIELD_UID("{shm_perm={", shmid_ds.shm_perm, uid); - PRINT_FIELD_UID(", ", shmid_ds.shm_perm, gid); - PRINT_FIELD_NUMERIC_UMODE_T(", ", shmid_ds.shm_perm, mode); - - if (cmd != IPC_SET) { - PRINT_FIELD_U(", ", shmid_ds.shm_perm, key); - PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cuid); - PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); - } - tprints("}"); - if (cmd != IPC_SET) { - PRINT_FIELD_U(", ", shmid_ds, shm_segsz); - PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); - PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); - PRINT_FIELD_U(", ", shmid_ds, shm_nattch); - PRINT_FIELD_U(", ", shmid_ds, shm_atime); - PRINT_FIELD_U(", ", shmid_ds, shm_dtime); - PRINT_FIELD_U(", ", shmid_ds, shm_ctime); - } - tprints("}"); - break; - default: - printaddr(addr); - break; + if (umove_or_printaddr(tcp, addr, &shmid_ds)) + return; + + PRINT_FIELD_UID("{shm_perm={", shmid_ds.shm_perm, uid); + PRINT_FIELD_UID(", ", shmid_ds.shm_perm, gid); + PRINT_FIELD_NUMERIC_UMODE_T(", ", shmid_ds.shm_perm, mode); + + if (cmd != IPC_SET) { + PRINT_FIELD_U(", ", shmid_ds.shm_perm, key); + PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cuid); + PRINT_FIELD_UID(", ", shmid_ds.shm_perm, cgid); } + tprints("}"); + if (cmd != IPC_SET) { + PRINT_FIELD_U(", ", shmid_ds, shm_segsz); + PRINT_FIELD_TGID(", ", shmid_ds, shm_cpid, tcp); + PRINT_FIELD_TGID(", ", shmid_ds, shm_lpid, tcp); + PRINT_FIELD_U(", ", shmid_ds, shm_nattch); + PRINT_FIELD_U(", ", shmid_ds, shm_atime); + PRINT_FIELD_U(", ", shmid_ds, shm_dtime); + PRINT_FIELD_U(", ", shmid_ds, shm_ctime); + } + tprints("}"); +} + +static void +print_shm_info(struct tcb *const tcp, const kernel_ulong_t addr, + const unsigned int cmd) +{ + struct_shm_info_t info; + + if (umove_or_printaddr(tcp, addr, &info)) + return; + + PRINT_FIELD_D("{", info, used_ids); + PRINT_FIELD_U(", ", info, shm_tot); + PRINT_FIELD_U(", ", info, shm_rss); + PRINT_FIELD_U(", ", info, shm_swp); + PRINT_FIELD_U(", ", info, swap_attempts); + PRINT_FIELD_U(", ", info, swap_successes); + tprints("}"); } SYS_FUNC(shmctl) @@ -78,7 +86,28 @@ SYS_FUNC(shmctl) tprints(", "); } else { const kernel_ulong_t addr = tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]; - print_shmid_ds(tcp, addr, tcp->u_arg[1]); + unsigned int cmd = tcp->u_arg[1]; + + /* TODO: We don't properly decode old compat ipc calls. */ + if (cmd & IPC_64) + cmd &= ~IPC_64; + + switch (cmd) { + case IPC_SET: + case IPC_STAT: + case SHM_STAT: + case SHM_STAT_ANY: + print_shmid_ds(tcp, addr, cmd); + break; + + case SHM_INFO: + print_shm_info(tcp, addr, cmd); + break; + + default: + printaddr(addr); + break; + } } return 0; } diff --git a/tests/ipc_shm.c b/tests/ipc_shm.c index 7f74f70c1..03568b1f5 100644 --- a/tests/ipc_shm.c +++ b/tests/ipc_shm.c @@ -117,6 +117,32 @@ print_shmid_ds(const char *const str_ipc_cmd, rc); } +static void +print_shm_info(const char *const str_ipc_cmd, + const struct shm_info *const info, + const int rc) +{ + if (rc < 0) { + printf("shmctl\\(%d, (%s\\|)?%s, %p\\) = %s\n", + id, str_ipc_64, str_ipc_cmd, info, sprintrc_grep(rc)); + return; + } + + printf("shmctl\\(%d, (%s\\|)?%s, \\{used_ids=%d, shm_tot=%llu" + ", shm_rss=%llu, shm_swp=%llu, swap_attempts=%llu" + ", swap_successes=%llu\\}\\) = %d\n", + id, + str_ipc_64, + str_ipc_cmd, + info->used_ids, + (unsigned long long) info->shm_tot, + (unsigned long long) info->shm_rss, + (unsigned long long) info->shm_swp, + (unsigned long long) info->swap_attempts, + (unsigned long long) info->swap_successes, + rc); +} + int main(void) { @@ -142,7 +168,10 @@ main(void) static const unsigned int huge_flags = 21 << SHM_HUGE_SHIFT; int bogus_flags; int rc; - struct shmid_ds ds; + union { + struct shmid_ds ds; + struct shm_info info; + } buf; rc = shmget(bogus_key, bogus_size, 0); printf("shmget\\(%#llx, %zu, 000\\) = %s\n", @@ -198,28 +227,28 @@ main(void) bogus_id, str_ipc_64, str_ipc_stat, bogus_addr, sprintrc_grep(rc)); - rc = shmctl(id, IPC_STAT, &ds); + rc = shmctl(id, IPC_STAT, &buf.ds); if (rc < 0) perror_msg_and_skip("shmctl IPC_STAT"); - print_shmid_ds(str_ipc_stat, &ds, rc); + print_shmid_ds(str_ipc_stat, &buf.ds, rc); - if (shmctl(id, IPC_SET, &ds)) + if (shmctl(id, IPC_SET, &buf.ds)) perror_msg_and_skip("shmctl IPC_SET"); printf("shmctl\\(%d, (%s\\|)?%s, \\{shm_perm=\\{uid=%u, gid=%u" ", mode=%#o\\}\\}\\) = 0\n", id, str_ipc_64, str_ipc_set, - (unsigned) ds.shm_perm.uid, (unsigned) ds.shm_perm.gid, - (unsigned) ds.shm_perm.mode); + (unsigned) buf.ds.shm_perm.uid, + (unsigned) buf.ds.shm_perm.gid, + (unsigned) buf.ds.shm_perm.mode); - rc = shmctl(0, SHM_INFO, &ds); - printf("shmctl\\(0, (%s\\|)?%s, %p\\) = %s\n", - str_ipc_64, str_shm_info, &ds, sprintrc_grep(rc)); + rc = shmctl(id, SHM_INFO, &buf.ds); + print_shm_info(str_shm_info, &buf.info, rc); - rc = shmctl(id, SHM_STAT, &ds); - print_shmid_ds(str_shm_stat, &ds, rc); + rc = shmctl(id, SHM_STAT, &buf.ds); + print_shmid_ds(str_shm_stat, &buf.ds, rc); - rc = shmctl(id, SHM_STAT_ANY, &ds); - print_shmid_ds(str_shm_stat_any, &ds, rc); + rc = shmctl(id, SHM_STAT_ANY, &buf.ds); + print_shmid_ds(str_shm_stat_any, &buf.ds, rc); return 0; } |