Accepting request 847890 from home:Andreas_Schwab:Factory
- intl-codeset-suffixes.patch: intl: Handle translation output codesets with suffixes (BZ #26383) - strerrorname-np.patch: string: Fix strerrorname_np return value (BZ #26555) - sysvipc.patch: sysvipc: Fix SEM_STAT_ANY kernel argument pass (BZ #26637, BZ #26639, BZ #26636) OBS-URL: https://build.opensuse.org/request/show/847890 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=572
This commit is contained in:
parent
88dbb21c8e
commit
f1d8923af9
@ -1,3 +1,13 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Nov 10 15:36:40 UTC 2020 - Andreas Schwab <schwab@suse.de>
|
||||
|
||||
- intl-codeset-suffixes.patch: intl: Handle translation output codesets
|
||||
with suffixes (BZ #26383)
|
||||
- strerrorname-np.patch: string: Fix strerrorname_np return value (BZ
|
||||
#26555)
|
||||
- sysvipc.patch: sysvipc: Fix SEM_STAT_ANY kernel argument pass (BZ
|
||||
#26637, BZ #26639, BZ #26636)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Oct 26 07:07:38 UTC 2020 - Richard Biener <rguenther@suse.com>
|
||||
|
||||
|
@ -263,6 +263,12 @@ Patch306: glibc-fix-double-loopback.diff
|
||||
Patch1000: syslog-locking.patch
|
||||
# PATCH-FIX-UPSTREAM x86-64: Fix FMA4 detection in ifunc (BZ #26534)
|
||||
Patch1001: ifunc-fma4.patch
|
||||
# PATCH-FIX-UPSTREAM intl: Handle translation output codesets with suffixes (BZ #26383)
|
||||
Patch1002: intl-codeset-suffixes.patch
|
||||
# PATCH-FIX-UPSTREAM string: Fix strerrorname_np return value (BZ #26555)
|
||||
Patch1003: strerrorname-np.patch
|
||||
# PATCH-FIX-UPSTREAM sysvipc: Fix SEM_STAT_ANY kernel argument pass (BZ #26637, BZ #26639, BZ #26636)
|
||||
Patch1004: sysvipc.patch
|
||||
|
||||
###
|
||||
# Patches awaiting upstream approval
|
||||
@ -477,6 +483,9 @@ makedb: A program to create a database for nss
|
||||
|
||||
%patch1000 -p1
|
||||
%patch1001 -p1
|
||||
%patch1002 -p1
|
||||
%patch1003 -p1
|
||||
%patch1004 -p1
|
||||
|
||||
%patch2000 -p1
|
||||
%patch2001 -p1
|
||||
|
237
intl-codeset-suffixes.patch
Normal file
237
intl-codeset-suffixes.patch
Normal file
@ -0,0 +1,237 @@
|
||||
From fe62c4d173f3cc1ac64f01e75a8f421b2f092cdb Mon Sep 17 00:00:00 2001
|
||||
From: Arjun Shankar <arjun@redhat.com>
|
||||
Date: Fri, 25 Sep 2020 14:47:06 +0200
|
||||
Subject: [PATCH] intl: Handle translation output codesets with suffixes [BZ
|
||||
#26383]
|
||||
|
||||
Commit 91927b7c7643 (Rewrite iconv option parsing [BZ #19519]) did not
|
||||
handle cases where the output codeset for translations (via the `gettext'
|
||||
family of functions) might have a caller specified encoding suffix such as
|
||||
TRANSLIT or IGNORE. This led to a regression where translations did not
|
||||
work when the codeset had a suffix.
|
||||
|
||||
This commit fixes the above issue by parsing any suffixes passed to
|
||||
__dcigettext and adds two new test-cases to intl/tst-codeset.c to
|
||||
verify correct behaviour. The iconv-internal function __gconv_create_spec
|
||||
and the static iconv-internal function gconv_destroy_spec are now visible
|
||||
internally within glibc and used in intl/dcigettext.c.
|
||||
|
||||
(cherry picked from commit 7d4ec75e111291851620c6aa2c4460647b7fd50d)
|
||||
---
|
||||
|
||||
Index: glibc-2.32/iconv/Versions
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/iconv/Versions
|
||||
+++ glibc-2.32/iconv/Versions
|
||||
@@ -6,7 +6,9 @@ libc {
|
||||
GLIBC_PRIVATE {
|
||||
# functions shared with iconv program
|
||||
__gconv_get_alias_db; __gconv_get_cache; __gconv_get_modules_db;
|
||||
- __gconv_open; __gconv_create_spec;
|
||||
+
|
||||
+ # functions used elsewhere in glibc
|
||||
+ __gconv_open; __gconv_create_spec; __gconv_destroy_spec;
|
||||
|
||||
# function used by the gconv modules
|
||||
__gconv_transliterate;
|
||||
Index: glibc-2.32/iconv/gconv_charset.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/iconv/gconv_charset.c
|
||||
+++ glibc-2.32/iconv/gconv_charset.c
|
||||
@@ -216,3 +216,13 @@ out:
|
||||
return ret;
|
||||
}
|
||||
libc_hidden_def (__gconv_create_spec)
|
||||
+
|
||||
+
|
||||
+void
|
||||
+__gconv_destroy_spec (struct gconv_spec *conv_spec)
|
||||
+{
|
||||
+ free (conv_spec->fromcode);
|
||||
+ free (conv_spec->tocode);
|
||||
+ return;
|
||||
+}
|
||||
+libc_hidden_def (__gconv_destroy_spec)
|
||||
Index: glibc-2.32/iconv/gconv_charset.h
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/iconv/gconv_charset.h
|
||||
+++ glibc-2.32/iconv/gconv_charset.h
|
||||
@@ -48,33 +48,6 @@
|
||||
#define GCONV_IGNORE_ERRORS_SUFFIX "IGNORE"
|
||||
|
||||
|
||||
-/* This function accepts the charset names of the source and destination of the
|
||||
- conversion and populates *conv_spec with an equivalent conversion
|
||||
- specification that may later be used by __gconv_open. The charset names
|
||||
- might contain options in the form of suffixes that alter the conversion,
|
||||
- e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring
|
||||
- and truncating any suffix options in fromcode, and processing and truncating
|
||||
- any suffix options in tocode. Supported suffix options ("TRANSLIT" or
|
||||
- "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
|
||||
- to be set to true. Unrecognized suffix options are silently discarded. If
|
||||
- the function succeeds, it returns conv_spec back to the caller. It returns
|
||||
- NULL upon failure. */
|
||||
-struct gconv_spec *
|
||||
-__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
|
||||
- const char *tocode);
|
||||
-libc_hidden_proto (__gconv_create_spec)
|
||||
-
|
||||
-
|
||||
-/* This function frees all heap memory allocated by __gconv_create_spec. */
|
||||
-static void __attribute__ ((unused))
|
||||
-gconv_destroy_spec (struct gconv_spec *conv_spec)
|
||||
-{
|
||||
- free (conv_spec->fromcode);
|
||||
- free (conv_spec->tocode);
|
||||
- return;
|
||||
-}
|
||||
-
|
||||
-
|
||||
/* This function copies in-order, characters from the source 's' that are
|
||||
either alpha-numeric or one in one of these: "_-.,:/" - into the destination
|
||||
'wp' while dropping all other characters. In the process, it converts all
|
||||
Index: glibc-2.32/iconv/gconv_int.h
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/iconv/gconv_int.h
|
||||
+++ glibc-2.32/iconv/gconv_int.h
|
||||
@@ -152,6 +152,27 @@ extern int __gconv_open (struct gconv_sp
|
||||
__gconv_t *handle, int flags);
|
||||
libc_hidden_proto (__gconv_open)
|
||||
|
||||
+/* This function accepts the charset names of the source and destination of the
|
||||
+ conversion and populates *conv_spec with an equivalent conversion
|
||||
+ specification that may later be used by __gconv_open. The charset names
|
||||
+ might contain options in the form of suffixes that alter the conversion,
|
||||
+ e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring
|
||||
+ and truncating any suffix options in fromcode, and processing and truncating
|
||||
+ any suffix options in tocode. Supported suffix options ("TRANSLIT" or
|
||||
+ "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
|
||||
+ to be set to true. Unrecognized suffix options are silently discarded. If
|
||||
+ the function succeeds, it returns conv_spec back to the caller. It returns
|
||||
+ NULL upon failure. */
|
||||
+extern struct gconv_spec *
|
||||
+__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
|
||||
+ const char *tocode);
|
||||
+libc_hidden_proto (__gconv_create_spec)
|
||||
+
|
||||
+/* This function frees all heap memory allocated by __gconv_create_spec. */
|
||||
+extern void
|
||||
+__gconv_destroy_spec (struct gconv_spec *conv_spec);
|
||||
+libc_hidden_proto (__gconv_destroy_spec)
|
||||
+
|
||||
/* Free resources associated with transformation descriptor CD. */
|
||||
extern int __gconv_close (__gconv_t cd)
|
||||
attribute_hidden;
|
||||
Index: glibc-2.32/iconv/iconv_open.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/iconv/iconv_open.c
|
||||
+++ glibc-2.32/iconv/iconv_open.c
|
||||
@@ -39,7 +39,7 @@ iconv_open (const char *tocode, const ch
|
||||
|
||||
int res = __gconv_open (&conv_spec, &cd, 0);
|
||||
|
||||
- gconv_destroy_spec (&conv_spec);
|
||||
+ __gconv_destroy_spec (&conv_spec);
|
||||
|
||||
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||
{
|
||||
Index: glibc-2.32/iconv/iconv_prog.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/iconv/iconv_prog.c
|
||||
+++ glibc-2.32/iconv/iconv_prog.c
|
||||
@@ -184,7 +184,7 @@ main (int argc, char *argv[])
|
||||
/* Let's see whether we have these coded character sets. */
|
||||
res = __gconv_open (&conv_spec, &cd, 0);
|
||||
|
||||
- gconv_destroy_spec (&conv_spec);
|
||||
+ __gconv_destroy_spec (&conv_spec);
|
||||
|
||||
if (res != __GCONV_OK)
|
||||
{
|
||||
Index: glibc-2.32/intl/dcigettext.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/intl/dcigettext.c
|
||||
+++ glibc-2.32/intl/dcigettext.c
|
||||
@@ -1121,15 +1121,18 @@ _nl_find_msg (struct loaded_l10nfile *do
|
||||
|
||||
# ifdef _LIBC
|
||||
|
||||
- struct gconv_spec conv_spec
|
||||
- = { .fromcode = norm_add_slashes (charset, ""),
|
||||
- .tocode = norm_add_slashes (outcharset, ""),
|
||||
- /* We always want to use transliteration. */
|
||||
- .translit = true,
|
||||
- .ignore = false
|
||||
- };
|
||||
+ struct gconv_spec conv_spec;
|
||||
+
|
||||
+ __gconv_create_spec (&conv_spec, charset, outcharset);
|
||||
+
|
||||
+ /* We always want to use transliteration. */
|
||||
+ conv_spec.translit = true;
|
||||
+
|
||||
int r = __gconv_open (&conv_spec, &convd->conv,
|
||||
GCONV_AVOID_NOCONV);
|
||||
+
|
||||
+ __gconv_destroy_spec (&conv_spec);
|
||||
+
|
||||
if (__builtin_expect (r != __GCONV_OK, 0))
|
||||
{
|
||||
/* If the output encoding is the same there is
|
||||
Index: glibc-2.32/intl/tst-codeset.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/intl/tst-codeset.c
|
||||
+++ glibc-2.32/intl/tst-codeset.c
|
||||
@@ -22,13 +22,11 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
+#include <support/check.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- char *s;
|
||||
- int result = 0;
|
||||
-
|
||||
unsetenv ("LANGUAGE");
|
||||
unsetenv ("OUTPUT_CHARSET");
|
||||
setlocale (LC_ALL, "de_DE.ISO-8859-1");
|
||||
@@ -36,25 +34,21 @@ do_test (void)
|
||||
bindtextdomain ("codeset", OBJPFX "domaindir");
|
||||
|
||||
/* Here we expect output in ISO-8859-1. */
|
||||
- s = gettext ("cheese");
|
||||
- if (strcmp (s, "K\344se"))
|
||||
- {
|
||||
- printf ("call 1 returned: %s\n", s);
|
||||
- result = 1;
|
||||
- }
|
||||
+ TEST_COMPARE_STRING (gettext ("cheese"), "K\344se");
|
||||
|
||||
+ /* Here we expect output in UTF-8. */
|
||||
bind_textdomain_codeset ("codeset", "UTF-8");
|
||||
+ TEST_COMPARE_STRING (gettext ("cheese"), "K\303\244se");
|
||||
|
||||
- /* Here we expect output in UTF-8. */
|
||||
- s = gettext ("cheese");
|
||||
- if (strcmp (s, "K\303\244se"))
|
||||
- {
|
||||
- printf ("call 2 returned: %s\n", s);
|
||||
- result = 1;
|
||||
- }
|
||||
+ /* `a with umlaut' is transliterated to `ae'. */
|
||||
+ bind_textdomain_codeset ("codeset", "ASCII//TRANSLIT");
|
||||
+ TEST_COMPARE_STRING (gettext ("cheese"), "Kaese");
|
||||
+
|
||||
+ /* Transliteration also works by default even if not set. */
|
||||
+ bind_textdomain_codeset ("codeset", "ASCII");
|
||||
+ TEST_COMPARE_STRING (gettext ("cheese"), "Kaese");
|
||||
|
||||
- return result;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-#define TEST_FUNCTION do_test ()
|
||||
-#include "../test-skeleton.c"
|
||||
+#include <support/test-driver.c>
|
1676
strerrorname-np.patch
Normal file
1676
strerrorname-np.patch
Normal file
File diff suppressed because it is too large
Load Diff
796
sysvipc.patch
Normal file
796
sysvipc.patch
Normal file
@ -0,0 +1,796 @@
|
||||
From 9b139b6b81a5def91bec01f30301acc95fbf0289 Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@altlinux.org>
|
||||
Date: Tue, 29 Sep 2020 14:10:20 -0300
|
||||
Subject: [PATCH] sysvipc: Fix SEM_STAT_ANY kernel argument pass [BZ #26637]
|
||||
|
||||
Handle SEM_STAT_ANY the same way as SEM_STAT so that the buffer argument
|
||||
of SEM_STAT_ANY is properly passed to the kernel and back.
|
||||
|
||||
The regression testcase checks for Linux specifix SysV ipc message
|
||||
control extension. For IPC_INFO/SEM_INFO it tries to match the values
|
||||
against the tunable /proc values and for SEM_STAT/SEM_STAT_ANY it
|
||||
check if the create message queue is within the global list returned
|
||||
by the kernel.
|
||||
|
||||
Checked on x86_64-linux-gnu and on i686-linux-gnu (Linux v5.4 and on
|
||||
Linux v4.15).
|
||||
|
||||
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
(cherry picked from commit 574500a108be1d2a6a0dc97a075c9e0a98371aba)
|
||||
|
||||
From c4aeedea598a1bd80f52ca9ebd07fe447680d491 Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue, 29 Sep 2020 14:39:56 -0300
|
||||
Subject: [PATCH] sysvipc: Fix IPC_INFO and MSG_INFO handling [BZ #26639]
|
||||
|
||||
Both commands are Linux extensions where the third argument is a
|
||||
'struct msginfo' instead of 'struct msqid_ds' and its information
|
||||
does not contain any time related fields (so there is no need to
|
||||
extra conversion for __IPC_TIME64.
|
||||
|
||||
The regression testcase checks for Linux specifix SysV ipc message
|
||||
control extension. For IPC_INFO/MSG_INFO it tries to match the values
|
||||
against the tunable /proc values and for MSG_STAT/MSG_STAT_ANY it
|
||||
check if the create message queue is within the global list returned
|
||||
by the kernel.
|
||||
|
||||
Checked on x86_64-linux-gnu and on i686-linux-gnu (Linux v5.4 and on
|
||||
Linux v4.15).
|
||||
|
||||
(cherry picked from commit 20a00dbefca5695cccaa44846a482db8ccdd85ab)
|
||||
|
||||
From 0b9460d22e285432d232f42c7442a3226e1bf830 Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue, 29 Sep 2020 14:51:36 -0300
|
||||
Subject: [PATCH] sysvipc: Fix IPC_INFO and SHM_INFO handling [BZ #26636]
|
||||
|
||||
Both commands are Linux extensions where the third argument is either
|
||||
a 'struct shminfo' (IPC_INFO) or a 'struct shm_info' (SHM_INFO) instead
|
||||
of 'struct shmid_ds'. And their information does not contain any time
|
||||
related fields, so there is no need to extra conversion for __IPC_TIME64.
|
||||
|
||||
The regression testcase checks for Linux specifix SysV ipc message
|
||||
control extension. For SHM_INFO it tries to match the values against the
|
||||
tunable /proc values and for MSG_STAT/MSG_STAT_ANY it check if the create\
|
||||
shared memory is within the global list returned by the kernel.
|
||||
|
||||
Checked on x86_64-linux-gnu and on i686-linux-gnu (Linux v5.4 and on
|
||||
Linux v4.15).
|
||||
|
||||
(cherry picked from commit a49d7fd4f764e97ccaf922e433046590ae52fce9)
|
||||
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/Makefile
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/sysdeps/unix/sysv/linux/Makefile
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/Makefile
|
||||
@@ -100,7 +100,7 @@ tests += tst-clone tst-clone2 tst-clone3
|
||||
tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
|
||||
test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
|
||||
tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
|
||||
- tst-tgkill
|
||||
+ tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux
|
||||
tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
|
||||
|
||||
CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/msgctl.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/sysdeps/unix/sysv/linux/msgctl.c
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/msgctl.c
|
||||
@@ -90,8 +90,15 @@ __msgctl64 (int msqid, int cmd, struct _
|
||||
struct kernel_msqid64_ds ksemid, *arg = NULL;
|
||||
if (buf != NULL)
|
||||
{
|
||||
- msqid64_to_kmsqid64 (buf, &ksemid);
|
||||
- arg = &ksemid;
|
||||
+ /* This is a Linux extension where kernel returns a 'struct msginfo'
|
||||
+ instead. */
|
||||
+ if (cmd == IPC_INFO || cmd == MSG_INFO)
|
||||
+ arg = (struct kernel_msqid64_ds *) buf;
|
||||
+ else
|
||||
+ {
|
||||
+ msqid64_to_kmsqid64 (buf, &ksemid);
|
||||
+ arg = &ksemid;
|
||||
+ }
|
||||
}
|
||||
# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
||||
if (cmd == IPC_SET)
|
||||
@@ -169,8 +176,15 @@ __msgctl (int msqid, int cmd, struct msq
|
||||
struct __msqid64_ds msqid64, *buf64 = NULL;
|
||||
if (buf != NULL)
|
||||
{
|
||||
- msqid_to_msqid64 (&msqid64, buf);
|
||||
- buf64 = &msqid64;
|
||||
+ /* This is a Linux extension where kernel returns a 'struct msginfo'
|
||||
+ instead. */
|
||||
+ if (cmd == IPC_INFO || cmd == MSG_INFO)
|
||||
+ buf64 = (struct __msqid64_ds *) buf;
|
||||
+ else
|
||||
+ {
|
||||
+ msqid_to_msqid64 (&msqid64, buf);
|
||||
+ buf64 = &msqid64;
|
||||
+ }
|
||||
}
|
||||
|
||||
int ret = __msgctl64 (msqid, cmd, buf64);
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/semctl.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/sysdeps/unix/sysv/linux/semctl.c
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/semctl.c
|
||||
@@ -102,6 +102,7 @@ semun64_to_ksemun64 (int cmd, union semu
|
||||
r.array = semun64.array;
|
||||
break;
|
||||
case SEM_STAT:
|
||||
+ case SEM_STAT_ANY:
|
||||
case IPC_STAT:
|
||||
case IPC_SET:
|
||||
r.buf = buf;
|
||||
@@ -150,6 +151,7 @@ __semctl64 (int semid, int semnum, int c
|
||||
case IPC_STAT: /* arg.buf */
|
||||
case IPC_SET:
|
||||
case SEM_STAT:
|
||||
+ case SEM_STAT_ANY:
|
||||
case IPC_INFO: /* arg.__buf */
|
||||
case SEM_INFO:
|
||||
va_start (ap, cmd);
|
||||
@@ -238,6 +240,7 @@ semun_to_semun64 (int cmd, union semun s
|
||||
r.array = semun.array;
|
||||
break;
|
||||
case SEM_STAT:
|
||||
+ case SEM_STAT_ANY:
|
||||
case IPC_STAT:
|
||||
case IPC_SET:
|
||||
r.buf = semid64;
|
||||
@@ -267,6 +270,7 @@ __semctl (int semid, int semnum, int cmd
|
||||
case IPC_STAT: /* arg.buf */
|
||||
case IPC_SET:
|
||||
case SEM_STAT:
|
||||
+ case SEM_STAT_ANY:
|
||||
case IPC_INFO: /* arg.__buf */
|
||||
case SEM_INFO:
|
||||
va_start (ap, cmd);
|
||||
@@ -321,6 +325,7 @@ __semctl_mode16 (int semid, int semnum,
|
||||
case IPC_STAT: /* arg.buf */
|
||||
case IPC_SET:
|
||||
case SEM_STAT:
|
||||
+ case SEM_STAT_ANY:
|
||||
case IPC_INFO: /* arg.__buf */
|
||||
case SEM_INFO:
|
||||
va_start (ap, cmd);
|
||||
@@ -354,6 +359,7 @@ __old_semctl (int semid, int semnum, int
|
||||
case IPC_STAT: /* arg.buf */
|
||||
case IPC_SET:
|
||||
case SEM_STAT:
|
||||
+ case SEM_STAT_ANY:
|
||||
case IPC_INFO: /* arg.__buf */
|
||||
case SEM_INFO:
|
||||
va_start (ap, cmd);
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/shmctl.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/sysdeps/unix/sysv/linux/shmctl.c
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/shmctl.c
|
||||
@@ -90,8 +90,15 @@ __shmctl64 (int shmid, int cmd, struct _
|
||||
struct kernel_shmid64_ds kshmid, *arg = NULL;
|
||||
if (buf != NULL)
|
||||
{
|
||||
- shmid64_to_kshmid64 (buf, &kshmid);
|
||||
- arg = &kshmid;
|
||||
+ /* This is a Linux extension where kernel expects either a
|
||||
+ 'struct shminfo' (IPC_INFO) or 'struct shm_info' (SHM_INFO). */
|
||||
+ if (cmd == IPC_INFO || cmd == SHM_INFO)
|
||||
+ arg = (struct kernel_shmid64_ds *) buf;
|
||||
+ else
|
||||
+ {
|
||||
+ shmid64_to_kshmid64 (buf, &kshmid);
|
||||
+ arg = &kshmid;
|
||||
+ }
|
||||
}
|
||||
# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
|
||||
if (cmd == IPC_SET)
|
||||
@@ -107,7 +114,6 @@ __shmctl64 (int shmid, int cmd, struct _
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
- case IPC_INFO:
|
||||
case IPC_STAT:
|
||||
case SHM_STAT:
|
||||
case SHM_STAT_ANY:
|
||||
@@ -168,8 +174,15 @@ __shmctl (int shmid, int cmd, struct shm
|
||||
struct __shmid64_ds shmid64, *buf64 = NULL;
|
||||
if (buf != NULL)
|
||||
{
|
||||
- shmid_to_shmid64 (&shmid64, buf);
|
||||
- buf64 = &shmid64;
|
||||
+ /* This is a Linux extension where kernel expects either a
|
||||
+ 'struct shminfo' (IPC_INFO) or 'struct shm_info' (SHM_INFO). */
|
||||
+ if (cmd == IPC_INFO || cmd == SHM_INFO)
|
||||
+ buf64 = (struct __shmid64_ds *) buf;
|
||||
+ else
|
||||
+ {
|
||||
+ shmid_to_shmid64 (&shmid64, buf);
|
||||
+ buf64 = &shmid64;
|
||||
+ }
|
||||
}
|
||||
|
||||
int ret = __shmctl64 (shmid, cmd, buf64);
|
||||
@@ -178,7 +191,6 @@ __shmctl (int shmid, int cmd, struct shm
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
- case IPC_INFO:
|
||||
case IPC_STAT:
|
||||
case SHM_STAT:
|
||||
case SHM_STAT_ANY:
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/tst-sysvmsg-linux.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/tst-sysvmsg-linux.c
|
||||
@@ -0,0 +1,177 @@
|
||||
+/* Basic tests for Linux SYSV message queue extensions.
|
||||
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sys/ipc.h>
|
||||
+#include <sys/msg.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/temp_file.h>
|
||||
+
|
||||
+#define MSGQ_MODE 0644
|
||||
+
|
||||
+/* These are for the temporary file we generate. */
|
||||
+static char *name;
|
||||
+static int msqid;
|
||||
+
|
||||
+static void
|
||||
+remove_msq (void)
|
||||
+{
|
||||
+ /* Enforce message queue removal in case of early test failure.
|
||||
+ Ignore error since the msg may already have being removed. */
|
||||
+ msgctl (msqid, IPC_RMID, NULL);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_prepare (int argc, char *argv[])
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (create_temp_file ("tst-sysvmsg.", &name) != -1);
|
||||
+}
|
||||
+
|
||||
+#define PREPARE do_prepare
|
||||
+
|
||||
+struct test_msginfo
|
||||
+{
|
||||
+ int msgmax;
|
||||
+ int msgmnb;
|
||||
+ int msgmni;
|
||||
+};
|
||||
+
|
||||
+/* It tries to obtain some system-wide SysV messsage queue information from
|
||||
+ /proc to check against IPC_INFO/MSG_INFO. The /proc only returns the
|
||||
+ tunables value of MSGMAX, MSGMNB, and MSGMNI.
|
||||
+
|
||||
+ The kernel also returns constant value for MSGSSZ, MSGSEG and also MSGMAP,
|
||||
+ MSGPOOL, and MSGTQL (for IPC_INFO). The issue to check them is they might
|
||||
+ change over kernel releases. */
|
||||
+
|
||||
+static int
|
||||
+read_proc_file (const char *file)
|
||||
+{
|
||||
+ FILE *f = fopen (file, "r");
|
||||
+ if (f == NULL)
|
||||
+ FAIL_UNSUPPORTED ("/proc is not mounted or %s is not available", file);
|
||||
+
|
||||
+ int v;
|
||||
+ int r = fscanf (f, "%d", & v);
|
||||
+ TEST_VERIFY_EXIT (r == 1);
|
||||
+
|
||||
+ fclose (f);
|
||||
+ return v;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Check if the message queue with IDX (index into the kernel's internal
|
||||
+ array) matches the one with KEY. The CMD is either MSG_STAT or
|
||||
+ MSG_STAT_ANY. */
|
||||
+
|
||||
+static bool
|
||||
+check_msginfo (int idx, key_t key, int cmd)
|
||||
+{
|
||||
+ struct msqid_ds msginfo;
|
||||
+ int mid = msgctl (idx, cmd, &msginfo);
|
||||
+ /* Ignore unused array slot returned by the kernel or information from
|
||||
+ unknown message queue. */
|
||||
+ if ((mid == -1 && errno == EINVAL) || mid != msqid)
|
||||
+ return false;
|
||||
+
|
||||
+ if (mid == -1)
|
||||
+ FAIL_EXIT1 ("msgctl with %s failed: %m",
|
||||
+ cmd == MSG_STAT ? "MSG_STAT" : "MSG_STAT_ANY");
|
||||
+
|
||||
+ TEST_COMPARE (msginfo.msg_perm.__key, key);
|
||||
+ TEST_COMPARE (msginfo.msg_perm.mode, MSGQ_MODE);
|
||||
+ TEST_COMPARE (msginfo.msg_qnum, 0);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ atexit (remove_msq);
|
||||
+
|
||||
+ key_t key = ftok (name, 'G');
|
||||
+ if (key == -1)
|
||||
+ FAIL_EXIT1 ("ftok failed: %m");
|
||||
+
|
||||
+ msqid = msgget (key, MSGQ_MODE | IPC_CREAT);
|
||||
+ if (msqid == -1)
|
||||
+ FAIL_EXIT1 ("msgget failed: %m");
|
||||
+
|
||||
+ struct test_msginfo tipcinfo;
|
||||
+ tipcinfo.msgmax = read_proc_file ("/proc/sys/kernel/msgmax");
|
||||
+ tipcinfo.msgmnb = read_proc_file ("/proc/sys/kernel/msgmnb");
|
||||
+ tipcinfo.msgmni = read_proc_file ("/proc/sys/kernel/msgmni");
|
||||
+
|
||||
+ int msqidx;
|
||||
+
|
||||
+ {
|
||||
+ struct msginfo ipcinfo;
|
||||
+ msqidx = msgctl (msqid, IPC_INFO, (struct msqid_ds *) &ipcinfo);
|
||||
+ if (msqidx == -1)
|
||||
+ FAIL_EXIT1 ("msgctl with IPC_INFO failed: %m");
|
||||
+
|
||||
+ TEST_COMPARE (ipcinfo.msgmax, tipcinfo.msgmax);
|
||||
+ TEST_COMPARE (ipcinfo.msgmnb, tipcinfo.msgmnb);
|
||||
+ TEST_COMPARE (ipcinfo.msgmni, tipcinfo.msgmni);
|
||||
+ }
|
||||
+
|
||||
+ /* Same as before but with MSG_INFO. */
|
||||
+ {
|
||||
+ struct msginfo ipcinfo;
|
||||
+ msqidx = msgctl (msqid, MSG_INFO, (struct msqid_ds *) &ipcinfo);
|
||||
+ if (msqidx == -1)
|
||||
+ FAIL_EXIT1 ("msgctl with IPC_INFO failed: %m");
|
||||
+
|
||||
+ TEST_COMPARE (ipcinfo.msgmax, tipcinfo.msgmax);
|
||||
+ TEST_COMPARE (ipcinfo.msgmnb, tipcinfo.msgmnb);
|
||||
+ TEST_COMPARE (ipcinfo.msgmni, tipcinfo.msgmni);
|
||||
+ }
|
||||
+
|
||||
+ /* We check if the created message queue shows in global list. */
|
||||
+ bool found = false;
|
||||
+ for (int i = 0; i <= msqidx; i++)
|
||||
+ {
|
||||
+ /* We can't tell apart if MSG_STAT_ANY is not supported (kernel older
|
||||
+ than 4.17) or if the index used is invalid. So it just check if the
|
||||
+ value returned from a valid call matches the created message
|
||||
+ queue. */
|
||||
+ check_msginfo (i, key, MSG_STAT_ANY);
|
||||
+
|
||||
+ if (check_msginfo (i, key, MSG_STAT))
|
||||
+ {
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ FAIL_EXIT1 ("msgctl with MSG_STAT/MSG_STAT_ANY could not find the "
|
||||
+ "created message queue");
|
||||
+
|
||||
+ if (msgctl (msqid, IPC_RMID, NULL) == -1)
|
||||
+ FAIL_EXIT1 ("msgctl failed");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/tst-sysvsem-linux.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/tst-sysvsem-linux.c
|
||||
@@ -0,0 +1,184 @@
|
||||
+/* Basic tests for Linux SYSV semaphore extensions.
|
||||
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sys/ipc.h>
|
||||
+#include <sys/sem.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/temp_file.h>
|
||||
+
|
||||
+/* These are for the temporary file we generate. */
|
||||
+static char *name;
|
||||
+static int semid;
|
||||
+
|
||||
+static void
|
||||
+remove_sem (void)
|
||||
+{
|
||||
+ /* Enforce message queue removal in case of early test failure.
|
||||
+ Ignore error since the sem may already have being removed. */
|
||||
+ semctl (semid, 0, IPC_RMID, 0);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_prepare (int argc, char *argv[])
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (create_temp_file ("tst-sysvsem.", &name) != -1);
|
||||
+}
|
||||
+
|
||||
+#define PREPARE do_prepare
|
||||
+
|
||||
+#define SEM_MODE 0644
|
||||
+
|
||||
+union semun
|
||||
+{
|
||||
+ int val;
|
||||
+ struct semid_ds *buf;
|
||||
+ unsigned short *array;
|
||||
+ struct seminfo *__buf;
|
||||
+};
|
||||
+
|
||||
+struct test_seminfo
|
||||
+{
|
||||
+ int semmsl;
|
||||
+ int semmns;
|
||||
+ int semopm;
|
||||
+ int semmni;
|
||||
+};
|
||||
+
|
||||
+/* It tries to obtain some system-wide SysV semaphore information from /proc
|
||||
+ to check against IPC_INFO/SEM_INFO. The /proc only returns the tunables
|
||||
+ value of SEMMSL, SEMMNS, SEMOPM, and SEMMNI.
|
||||
+
|
||||
+ The kernel also returns constant value for SEMVMX, SEMMNU, SEMMAP, SEMUME,
|
||||
+ and also SEMUSZ and SEMAEM (for IPC_INFO). The issue to check them is they
|
||||
+ might change over kernel releases. */
|
||||
+
|
||||
+static void
|
||||
+read_sem_stat (struct test_seminfo *tseminfo)
|
||||
+{
|
||||
+ FILE *f = fopen ("/proc/sys/kernel/sem", "r");
|
||||
+ if (f == NULL)
|
||||
+ FAIL_UNSUPPORTED ("/proc is not mounted or /proc/sys/kernel/sem is not "
|
||||
+ "available");
|
||||
+
|
||||
+ int r = fscanf (f, "%d %d %d %d",
|
||||
+ &tseminfo->semmsl, &tseminfo->semmns, &tseminfo->semopm,
|
||||
+ &tseminfo->semmni);
|
||||
+ TEST_VERIFY_EXIT (r == 4);
|
||||
+
|
||||
+ fclose (f);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Check if the semaphore with IDX (index into the kernel's internal array)
|
||||
+ matches the one with KEY. The CMD is either SEM_STAT or SEM_STAT_ANY. */
|
||||
+
|
||||
+static bool
|
||||
+check_seminfo (int idx, key_t key, int cmd)
|
||||
+{
|
||||
+ struct semid_ds seminfo;
|
||||
+ int sid = semctl (idx, 0, cmd, (union semun) { .buf = &seminfo });
|
||||
+ /* Ignore unused array slot returned by the kernel or information from
|
||||
+ unknown semaphores. */
|
||||
+ if ((sid == -1 && errno == EINVAL) || sid != semid)
|
||||
+ return false;
|
||||
+
|
||||
+ if (sid == -1)
|
||||
+ FAIL_EXIT1 ("semctl with SEM_STAT failed (errno=%d)", errno);
|
||||
+
|
||||
+ TEST_COMPARE (seminfo.sem_perm.__key, key);
|
||||
+ TEST_COMPARE (seminfo.sem_perm.mode, SEM_MODE);
|
||||
+ TEST_COMPARE (seminfo.sem_nsems, 1);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ atexit (remove_sem);
|
||||
+
|
||||
+ key_t key = ftok (name, 'G');
|
||||
+ if (key == -1)
|
||||
+ FAIL_EXIT1 ("ftok failed: %m");
|
||||
+
|
||||
+ semid = semget (key, 1, IPC_CREAT | IPC_EXCL | SEM_MODE);
|
||||
+ if (semid == -1)
|
||||
+ FAIL_EXIT1 ("semget failed: %m");
|
||||
+
|
||||
+ struct test_seminfo tipcinfo;
|
||||
+ read_sem_stat (&tipcinfo);
|
||||
+
|
||||
+ int semidx;
|
||||
+
|
||||
+ {
|
||||
+ struct seminfo ipcinfo;
|
||||
+ semidx = semctl (semid, 0, IPC_INFO, (union semun) { .__buf = &ipcinfo });
|
||||
+ if (semidx == -1)
|
||||
+ FAIL_EXIT1 ("semctl with IPC_INFO failed: %m");
|
||||
+
|
||||
+ TEST_COMPARE (ipcinfo.semmsl, tipcinfo.semmsl);
|
||||
+ TEST_COMPARE (ipcinfo.semmns, tipcinfo.semmns);
|
||||
+ TEST_COMPARE (ipcinfo.semopm, tipcinfo.semopm);
|
||||
+ TEST_COMPARE (ipcinfo.semmni, tipcinfo.semmni);
|
||||
+ }
|
||||
+
|
||||
+ /* Same as before but with SEM_INFO. */
|
||||
+ {
|
||||
+ struct seminfo ipcinfo;
|
||||
+ semidx = semctl (semid, 0, SEM_INFO, (union semun) { .__buf = &ipcinfo });
|
||||
+ if (semidx == -1)
|
||||
+ FAIL_EXIT1 ("semctl with IPC_INFO failed: %m");
|
||||
+
|
||||
+ TEST_COMPARE (ipcinfo.semmsl, tipcinfo.semmsl);
|
||||
+ TEST_COMPARE (ipcinfo.semmns, tipcinfo.semmns);
|
||||
+ TEST_COMPARE (ipcinfo.semopm, tipcinfo.semopm);
|
||||
+ TEST_COMPARE (ipcinfo.semmni, tipcinfo.semmni);
|
||||
+ }
|
||||
+
|
||||
+ /* We check if the created semaphore shows in the system-wide status. */
|
||||
+ bool found = false;
|
||||
+ for (int i = 0; i <= semidx; i++)
|
||||
+ {
|
||||
+ /* We can't tell apart if SEM_STAT_ANY is not supported (kernel older
|
||||
+ than 4.17) or if the index used is invalid. So it just check if
|
||||
+ value returned from a valid call matches the created semaphore. */
|
||||
+ check_seminfo (i, key, SEM_STAT_ANY);
|
||||
+
|
||||
+ if (check_seminfo (i, key, SEM_STAT))
|
||||
+ {
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ FAIL_EXIT1 ("semctl with SEM_STAT/SEM_STAT_ANY could not find the "
|
||||
+ "created semaphore");
|
||||
+
|
||||
+ if (semctl (semid, 0, IPC_RMID, 0) == -1)
|
||||
+ FAIL_EXIT1 ("semctl failed: %m");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
Index: glibc-2.32/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ glibc-2.32/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
|
||||
@@ -0,0 +1,185 @@
|
||||
+/* Basic tests for Linux SYSV shared memory extensions.
|
||||
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sys/ipc.h>
|
||||
+#include <sys/shm.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <unistd.h>
|
||||
+#include <inttypes.h>
|
||||
+#include <limits.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/temp_file.h>
|
||||
+
|
||||
+#define SHM_MODE 0644
|
||||
+
|
||||
+/* These are for the temporary file we generate. */
|
||||
+static char *name;
|
||||
+static int shmid;
|
||||
+static long int pgsz;
|
||||
+
|
||||
+static void
|
||||
+remove_shm (void)
|
||||
+{
|
||||
+ /* Enforce message queue removal in case of early test failure.
|
||||
+ Ignore error since the shm may already have being removed. */
|
||||
+ shmctl (shmid, IPC_RMID, NULL);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_prepare (int argc, char *argv[])
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (create_temp_file ("tst-sysvshm.", &name) != -1);
|
||||
+}
|
||||
+
|
||||
+#define PREPARE do_prepare
|
||||
+
|
||||
+struct test_shminfo
|
||||
+{
|
||||
+ unsigned long int shmall;
|
||||
+ unsigned long int shmmax;
|
||||
+ unsigned long int shmmni;
|
||||
+};
|
||||
+
|
||||
+/* It tries to obtain some system-wide SysV shared memory information from
|
||||
+ /proc to check against IPC_INFO/SHM_INFO. The /proc only returns the
|
||||
+ tunables value of SHMALL, SHMMAX, and SHMMNI. */
|
||||
+
|
||||
+static uint64_t
|
||||
+read_proc_file (const char *file)
|
||||
+{
|
||||
+ FILE *f = fopen (file, "r");
|
||||
+ if (f == NULL)
|
||||
+ FAIL_UNSUPPORTED ("/proc is not mounted or %s is not available", file);
|
||||
+
|
||||
+ /* Handle 32-bit binaries running on 64-bit kernels. */
|
||||
+ uint64_t v;
|
||||
+ int r = fscanf (f, "%" SCNu64, &v);
|
||||
+ TEST_VERIFY_EXIT (r == 1);
|
||||
+
|
||||
+ fclose (f);
|
||||
+ return v;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Check if the message queue with IDX (index into the kernel's internal
|
||||
+ array) matches the one with KEY. The CMD is either SHM_STAT or
|
||||
+ SHM_STAT_ANY. */
|
||||
+
|
||||
+static bool
|
||||
+check_shminfo (int idx, key_t key, int cmd)
|
||||
+{
|
||||
+ struct shmid_ds shminfo;
|
||||
+ int sid = shmctl (idx, cmd, &shminfo);
|
||||
+ /* Ignore unused array slot returned by the kernel or information from
|
||||
+ unknown message queue. */
|
||||
+ if ((sid == -1 && errno == EINVAL) || sid != shmid)
|
||||
+ return false;
|
||||
+
|
||||
+ if (sid == -1)
|
||||
+ FAIL_EXIT1 ("shmctl with %s failed: %m",
|
||||
+ cmd == SHM_STAT ? "SHM_STAT" : "SHM_STAT_ANY");
|
||||
+
|
||||
+ TEST_COMPARE (shminfo.shm_perm.__key, key);
|
||||
+ TEST_COMPARE (shminfo.shm_perm.mode, SHM_MODE);
|
||||
+ TEST_COMPARE (shminfo.shm_segsz, pgsz);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ atexit (remove_shm);
|
||||
+
|
||||
+ pgsz = sysconf (_SC_PAGESIZE);
|
||||
+ if (pgsz == -1)
|
||||
+ FAIL_EXIT1 ("sysconf (_SC_PAGESIZE) failed: %m");
|
||||
+
|
||||
+ key_t key = ftok (name, 'G');
|
||||
+ if (key == -1)
|
||||
+ FAIL_EXIT1 ("ftok failed: %m");
|
||||
+
|
||||
+ shmid = shmget (key, pgsz, IPC_CREAT | IPC_EXCL | SHM_MODE);
|
||||
+ if (shmid == -1)
|
||||
+ FAIL_EXIT1 ("shmget failed: %m");
|
||||
+
|
||||
+ struct test_shminfo tipcinfo;
|
||||
+ {
|
||||
+ uint64_t v = read_proc_file ("/proc/sys/kernel/shmmax");
|
||||
+#if LONG_MAX == INT_MAX
|
||||
+ /* Kernel explicit clamp the value for shmmax on compat symbol (32-bit
|
||||
+ binaries running on 64-bit kernels). */
|
||||
+ if (v > INT_MAX)
|
||||
+ v = INT_MAX;
|
||||
+#endif
|
||||
+ tipcinfo.shmmax = v;
|
||||
+ }
|
||||
+ tipcinfo.shmall = read_proc_file ("/proc/sys/kernel/shmall");
|
||||
+ tipcinfo.shmmni = read_proc_file ("/proc/sys/kernel/shmmni");
|
||||
+
|
||||
+ int shmidx;
|
||||
+
|
||||
+ /* Note: SHM_INFO does not return a shminfo, but rather a 'struct shm_info'.
|
||||
+ It is tricky to verify its values since the syscall returns system wide
|
||||
+ resources consumed by shared memory. The shmctl implementation handles
|
||||
+ SHM_INFO as IPC_INFO, so the IPC_INFO test should validate SHM_INFO as
|
||||
+ well. */
|
||||
+
|
||||
+ {
|
||||
+ struct shminfo ipcinfo;
|
||||
+ shmidx = shmctl (shmid, IPC_INFO, (struct shmid_ds *) &ipcinfo);
|
||||
+ if (shmidx == -1)
|
||||
+ FAIL_EXIT1 ("shmctl with IPC_INFO failed: %m");
|
||||
+
|
||||
+ TEST_COMPARE (ipcinfo.shmall, tipcinfo.shmall);
|
||||
+ TEST_COMPARE (ipcinfo.shmmax, tipcinfo.shmmax);
|
||||
+ TEST_COMPARE (ipcinfo.shmmni, tipcinfo.shmmni);
|
||||
+ }
|
||||
+
|
||||
+ /* We check if the created shared memory shows in the global list. */
|
||||
+ bool found = false;
|
||||
+ for (int i = 0; i <= shmidx; i++)
|
||||
+ {
|
||||
+ /* We can't tell apart if SHM_STAT_ANY is not supported (kernel older
|
||||
+ than 4.17) or if the index used is invalid. So it just check if
|
||||
+ value returned from a valid call matches the created message
|
||||
+ queue. */
|
||||
+ check_shminfo (i, key, SHM_STAT_ANY);
|
||||
+
|
||||
+ if (check_shminfo (i, key, SHM_STAT))
|
||||
+ {
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ FAIL_EXIT1 ("shmctl with SHM_STAT/SHM_STAT_ANY could not find the "
|
||||
+ "created shared memory");
|
||||
+
|
||||
+ if (shmctl (shmid, IPC_RMID, NULL) == -1)
|
||||
+ FAIL_EXIT1 ("shmctl failed");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
Index: glibc-2.32/sysvipc/test-sysvsem.c
|
||||
===================================================================
|
||||
--- glibc-2.32.orig/sysvipc/test-sysvsem.c
|
||||
+++ glibc-2.32/sysvipc/test-sysvsem.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
+#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
Loading…
Reference in New Issue
Block a user