Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:GA
crash.10062
crash-Fix-and-an-update-for-the-ipcs-command.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File crash-Fix-and-an-update-for-the-ipcs-command.patch of Package crash.10062
From 759dc0c50dc6cc3199e56be57cb57d41812b0397 Mon Sep 17 00:00:00 2001 From: Dave Anderson <anderson@redhat.com> Date: Mon, 30 Apr 2018 10:38:26 -0400 Subject: [PATCH] Fix, and an update, for the "ipcs" command. The fix addresses an error where IPCS entries are not displayed because of a faulty read of the "deleted" member of the embedded "kern_ipc_perm" data structure. The "deleted" member was being read as a 4-byte integer, but since it is declared as a "bool" type, only the lowest byte gets set to 1 or 0. Since the structure is not zeroed-out when allocated, stale data may be left in the upper 3 bytes, and the IPCS entry gets rejected. The update is required for Linux 4.11 and greater kernels, which reimplemented the IDR facility to use radix trees in kernel commit 0a835c4f090af2c76fc2932c539c3b32fd21fbbb, titled "Reimplement IDR and IDA using the radix tree". Without the patch, if any IPCS entry exists, the command would fail with the message "ipcs: invalid structure member offset: idr_top" (anderson@redhat.com) References: bsc#1092101 Patch-mainline: 7.2.2 Git-commit: 759dc0c50dc6cc3199e56be57cb57d41812b0397 --- ipcs.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/ipcs.c b/ipcs.c index 4fa9ab428fdb..ef51fddd33b8 100644 --- a/ipcs.c +++ b/ipcs.c @@ -71,6 +71,8 @@ struct ipcs_table { ulong shm_f_op_huge_addr; int use_shm_f_op; int seq_multiplier; + int rt_cnt; + struct radix_tree_pair *rtp; }; /* @@ -92,6 +94,7 @@ static void get_sem_info(struct sem_info *, ulong, int); static void get_msg_info(struct msg_info *, ulong, int); static void add_rss_swap(ulong, int, ulong *, ulong *); static int is_file_hugepages(ulong); +static void gather_radix_tree_entries(ulong); /* * global data @@ -574,7 +577,7 @@ ipc_search_array(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn static int ipc_search_idr(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(ulong, int, ulong, int, int), int verbose) { - int in_use; + int i, in_use; ulong ipcs_idr_p; ulong ipc; int next_id, total; @@ -591,16 +594,32 @@ ipc_search_idr(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)( return 0; } - for (total = 0, next_id = 0; total < in_use; next_id++) { - ipc = idr_find(ipcs_idr_p, next_id); - if (ipc == 0) - continue; - - total++; - if (fn(ipc, specified, specified_value, next_id, verbose)) { - found = 1; - if (specified != SPECIFIED_NOTHING) - break; + if (VALID_MEMBER(idr_idr_rt)) { + gather_radix_tree_entries(ipcs_idr_p); + + for (i = 0; i < ipcs_table.rt_cnt; i++) { + ipc = (ulong)ipcs_table.rtp[i].value; + if (fn(ipc, specified, specified_value, UNUSED, verbose)) { + found = 1; + if (specified != SPECIFIED_NOTHING) + break; + } + } + + if (ipcs_table.rtp) + FREEBUF(ipcs_table.rtp); + } else { + for (total = 0, next_id = 0; total < in_use; next_id++) { + ipc = idr_find(ipcs_idr_p, next_id); + if (ipc == 0) + continue; + + total++; + if (fn(ipc, specified, specified_value, next_id, verbose)) { + found = 1; + if (specified != SPECIFIED_NOTHING) + break; + } } } @@ -885,7 +904,7 @@ get_shm_info(struct shm_info *shm_info, ulong shp, int id) add_rss_swap(inodep, is_file_hugepages(filep), &shm_info->rss, &shm_info->swap); - shm_info->deleted = UINT(buf + OFFSET(shmid_kernel_shm_perm) + + shm_info->deleted = UCHAR(buf + OFFSET(shmid_kernel_shm_perm) + OFFSET(kern_ipc_perm_deleted)); } @@ -930,7 +949,7 @@ get_sem_info(struct sem_info *sem_info, ulong shp, int id) sem_info->nsems = ULONG(buf + OFFSET(sem_array_sem_nsems)); - sem_info->deleted = UINT(buf + OFFSET(sem_array_sem_perm) + + sem_info->deleted = UCHAR(buf + OFFSET(sem_array_sem_perm) + OFFSET(kern_ipc_perm_deleted)); } @@ -976,7 +995,7 @@ get_msg_info(struct msg_info *msg_info, ulong shp, int id) msg_info->messages = ULONG(buf + OFFSET(msg_queue_q_qnum)); - msg_info->deleted = UINT(buf + OFFSET(msg_queue_q_perm) + + msg_info->deleted = UCHAR(buf + OFFSET(msg_queue_q_perm) + OFFSET(kern_ipc_perm_deleted)); } @@ -1083,3 +1102,19 @@ again: return 0; } +static void +gather_radix_tree_entries(ulong ipcs_idr_p) +{ + long len; + + ipcs_table.rt_cnt = do_radix_tree(ipcs_idr_p, RADIX_TREE_COUNT, NULL); + + if (ipcs_table.rt_cnt) { + len = sizeof(struct radix_tree_pair) * (ipcs_table.rt_cnt+1); + ipcs_table.rtp = (struct radix_tree_pair *)GETBUF(len); + ipcs_table.rtp[0].index = ipcs_table.rt_cnt; + ipcs_table.rt_cnt = do_radix_tree(ipcs_idr_p, RADIX_TREE_GATHER, ipcs_table.rtp); + } else + ipcs_table.rtp = NULL; +} + -- 2.13.7
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor