]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
setarch: add -p/--pid option showing the personality of specified process
authorMasatake YAMATO <yamato@redhat.com>
Tue, 25 Mar 2025 19:49:02 +0000 (04:49 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Fri, 28 Mar 2025 10:08:01 +0000 (19:08 +0900)
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
bash-completion/setarch
sys-utils/setarch.8.adoc
sys-utils/setarch.c
tests/expected/setarch/pid-without-show [new file with mode: 0644]
tests/expected/setarch/pid-without-show.err [new file with mode: 0644]
tests/expected/setarch/show-with-pid [new file with mode: 0644]
tests/ts/setarch/pid-without-show [new file with mode: 0755]
tests/ts/setarch/show-with-pid [new file with mode: 0755]

index 7d7bdb00c5b692dd9ba7f7496c79e0483a5e570c..9546eb29245ab2fc3d1774ebf90d54571d16bffd 100644 (file)
@@ -4,10 +4,29 @@ _setarch_module()
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        prev="${COMP_WORDS[COMP_CWORD-1]}"
+       pprev="${COMP_WORDS[COMP_CWORD-2]}"
+       case $pprev in
+               '-p'|'--pid')
+                       COMPREPLY=( $(compgen -W "--show" -- $cur) )
+                       return 0
+                       ;;
+       esac
        case $prev in
                '-h'|'--help'|'-V'|'--version')
                        return 0
                        ;;
+               '-p'|'--pid')
+                       COMPREPLY=( $(compgen -W "$(cd /proc && echo [0-9]*)" -- $cur) )
+                       return 0
+                       ;;
+               '--show')
+                       OPTS="
+                               current
+                               --pid
+                       "
+                       COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
+                       return 0
+                       ;;
        esac
        if [ $COMP_CWORD -eq 1 ]; then
                OPTS="$($1 --list)"
index 7c64aed7ce929df1a33091b0f98916de9b810271..1d8c390b3f74e0b056de1cec02750ffbe631aad2 100644 (file)
@@ -35,6 +35,8 @@ List the architectures that *setarch* knows about. Whether *setarch* can actuall
 Show the currently active personality and flags.
 If the *personality* argument is provided, it is shown instead of the current one.
 *personality* is a hexadecimal number with values was described in *sys/personality.h*.
++
+If *--pid=pid* option is provided, show them of the specifies process.
 
 *--uname-2.6*::
 Causes the _program_ to see a kernel version number beginning with 2.6. Turns on *UNAME26*.
@@ -48,6 +50,9 @@ Specifies _program_ should use a maximum of 3GB of address space. Supported on x
 *--4gb*::
 This option has no effect. It is retained for backward compatibility only, and may be removed in future releases.
 
+*-p*, *--pid=pid*::
+With *--show* option, show the currently active personality and flags of the specifies process.
+
 *-B*, *--32bit*::
 Limit the address space to 32 bits to emulate hardware. Supported on ARM and Alpha. Turns on *ADDR_LIMIT_32BIT*.
 
@@ -84,6 +89,9 @@ setarch --addr-no-randomize mytestprog
 setarch ppc32 rpmbuild --target=ppc --rebuild foo.src.rpm
 setarch ppc32 -v -vL3 rpmbuild --target=ppc --rebuild bar.src.rpm
 setarch ppc32 --32bit rpmbuild --target=ppc --rebuild foo.src.rpm
+setarch --show
+setarch --show=$(cat /proc/9284/personality)
+setarch --show --pid 9284
 ....
 
 == AUTHORS
@@ -96,6 +104,7 @@ mailto:kzak@redhat.com[Karel Zak]
 
 *personality*(2),
 *select*(2)
+*proc_pid_personality(5)
 
 include::man-common/bugreports.adoc[]
 
index 4bcb5e69e67c41cf0a2568121132b4ffce765e46..c5a2751f6f49136da1f6a5870abfd1bcf8d1cc3c 100644 (file)
@@ -37,6 +37,7 @@
 #include "closestream.h"
 #include "sysfs.h"
 #include "strutils.h"
+#include "procfs.h"
 
 #ifndef HAVE_PERSONALITY
 # include <syscall.h>
@@ -169,6 +170,7 @@ static void __attribute__((__noreturn__)) usage(int archwrapper)
        if (!archwrapper) {
                fputs(_("     --list               list settable architectures, and exit\n"), stdout);
                fputs(_("     --show[=personality] show current or specific personality and exit\n"), stdout);
+               fputs(_(" -p, --pid=PID            show the personality of the process using with --show\n"), stdout);
        }
 
        fputs(USAGE_SEPARATOR, stdout);
@@ -424,6 +426,24 @@ static void show_current_personality(void)
        show_personality(pers);
 }
 
+static void show_process_personality(pid_t pid)
+{
+       int pers;
+       char *pers_str;
+
+       pers_str = pid_get_personality(pid);
+       if (pers_str == NULL)
+               err(EXIT_FAILURE,
+                   _("Can not get the personality for process(%d)"),
+                   pid);
+       pers = str2num_or_err(pers_str, 16,
+                             _("could not parse personality"),
+                             0, INT_MAX);
+       free(pers_str);
+
+       show_personality(pers);
+}
+
 int main(int argc, char *argv[])
 {
        const char *arch = NULL;
@@ -434,6 +454,8 @@ int main(int argc, char *argv[])
        struct arch_domain *doms = NULL, *target = NULL;
        unsigned long pers_value = 0;
        char *shell = NULL, *shell_arg = NULL;
+       int do_show = 0;
+       pid_t target_pid = 0;
 
        /* Options without equivalent short options */
        enum {
@@ -463,6 +485,7 @@ int main(int argc, char *argv[])
                {"uname-2.6",           no_argument,            NULL,   OPT_UNAME26},
                {"list",                no_argument,            NULL,   OPT_LIST},
                {"show",                optional_argument,      NULL,   OPT_SHOW},
+               {"pid",                 required_argument,      NULL,   'p'},
                {NULL,                  0,                      NULL,   0}
        };
 
@@ -495,7 +518,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZ", longopts, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZp:", longopts, NULL)) != -1) {
                switch (c) {
                case 'v':
                        verbose = 1;
@@ -542,9 +565,22 @@ int main(int argc, char *argv[])
                        } else
                                warnx(_("unrecognized option '--list'"));
                        goto error_getopts;
+               case 'p':
+                       if (!archwrapper) {
+                               target_pid = strtos32_or_err(optarg, _("invalid PID argument"));
+                               if (target_pid <= 0)
+                                       errx(EXIT_FAILURE, _("out of range value for pid specification: %d"),
+                                            target_pid);
+                               break;
+                       } else
+                               warnx(_("unrecognized option '%s'"), argv[optind - 1]);
+                       goto error_getopts;
                case OPT_SHOW:
                        if (!archwrapper) {
-                               if (!optarg || strcmp(optarg, "current") == 0)
+                               if (!optarg) {
+                                       do_show = 1;
+                                       break;
+                               } else if (strcmp(optarg, "current") == 0)
                                        show_current_personality();
                                else
                                        show_personality(str2num_or_err(
@@ -566,6 +602,17 @@ error_getopts:
                }
        }
 
+       /* We could not find --pid option though we saw --show option. */
+       if (do_show) {
+               if (target_pid)
+                       show_process_personality(target_pid);
+               else
+                       show_current_personality();
+               return EXIT_SUCCESS;
+       }
+       if (target_pid)
+               errx(EXIT_FAILURE, _("use -p/--pid option with --show option"));
+
        if (!arch && !options)
                errx(EXIT_FAILURE, _("no architecture argument or personality flags specified"));
 
diff --git a/tests/expected/setarch/pid-without-show b/tests/expected/setarch/pid-without-show
new file mode 100644 (file)
index 0000000..a9bf5a0
--- /dev/null
@@ -0,0 +1 @@
+exit status: 1
diff --git a/tests/expected/setarch/pid-without-show.err b/tests/expected/setarch/pid-without-show.err
new file mode 100644 (file)
index 0000000..e0242f9
--- /dev/null
@@ -0,0 +1 @@
+setarch: use -p/--pid option with --show option
diff --git a/tests/expected/setarch/show-with-pid b/tests/expected/setarch/show-with-pid
new file mode 100644 (file)
index 0000000..d86bac9
--- /dev/null
@@ -0,0 +1 @@
+OK
diff --git a/tests/ts/setarch/pid-without-show b/tests/ts/setarch/pid-without-show
new file mode 100755 (executable)
index 0000000..5fbf9d0
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash
+#
+# Copyright (C) 2025 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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 General Public License for more details.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="--show --pid options"
+
+. "$TS_TOPDIR"/functions.sh
+
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_SETARCH"
+
+ts_cd "$TS_OUTDIR"
+
+LC_ALL=C "$TS_CMD_SETARCH" --pid=$$ 2 2> $TS_ERRLOG > $TS_OUTPUT
+echo "exit status: $?" >> $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/setarch/show-with-pid b/tests/ts/setarch/show-with-pid
new file mode 100755 (executable)
index 0000000..8f5c439
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/bash
+#
+# Copyright (C) 2025 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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 General Public License for more details.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="--show --pid options"
+
+. "$TS_TOPDIR"/functions.sh
+
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_SETARCH"
+ts_check_prog "cat"
+
+ts_cd "$TS_OUTDIR"
+
+if ! "$TS_CMD_SETARCH" -R bash -c 'echo $$; cat' < /dev/null 1 > /dev/null 2>&1; then
+    ts_skip "--addr-no-randomize doesn't work on this platform"
+fi
+
+SKIP_REASON=
+{
+    PID=
+    coproc BASH { "$TS_CMD_SETARCH" -R bash -c 'echo $$; cat'; }
+    if read -u ${BASH[0]} PID; then
+       personality_file="/proc/$PID/personality"
+       if personality=$(cat "$personality_file"); then
+           DIRECT=$("$TS_CMD_SETARCH" --show="$personality")
+           INDIRECT=$("$TS_CMD_SETARCH" --show --pid="$PID")
+           if [[ "$DIRECT" == "$INDIRECT" ]]; then
+               echo OK
+           else
+               echo DIRECT: "$DIRECT"
+               echo INDIRECT: "$INDIRECT"
+           fi
+       else
+           SKIP_REASON="cannot read $personality_file on this platform"
+       fi
+    fi
+    exec {BASH[1]}>&-
+    wait ${BASH_PID}
+}  > $TS_OUTPUT 2>&1
+
+if [[ -n "$SKIP_REASON" ]]; then
+    ts_skip "$SKIP_REASON"
+fi
+
+ts_finalize