summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2020-09-19 08:00:00 +0000
committerDmitry V. Levin <ldv@altlinux.org>2020-09-19 08:00:00 +0000
commit42e8d663e3edbb34f9d25fc5801fb85fa4bf8818 (patch)
tree54469ecf9e78df3825c66b84c49a48d7eb9e5a45
parent9282c8a4151f1ad5914ac24eb23d05449ea1cb8c (diff)
downloadstrace-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--NEWS2
-rw-r--r--ipc_shmctl.c103
-rw-r--r--tests/ipc_shm.c55
3 files changed, 110 insertions, 50 deletions
diff --git a/NEWS b/NEWS
index dfc7db9d0..5ea586cac 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
}