Найдите максимум в каждых 10 строках в определенном столбце и распечатайте всю строку

Это можно сделать с помощьюgdbотладчика, и если запущенный процесс можно присоединить к (программам, которые изменяют свое дампируемое состояние или имеют setgid и т. д., к ним нельзя присоединить, если только от корня ).

Некоторые необязательные файлы могут помочь использовать gdb, например символы отладки для libc6, а также несколько файлов include, связанных с Linux, для получения фактических значений нескольких символов позже (например, в Debian:(возможно )libc6-dbg, libc6-devи linux-libc-devпакеты ), но на самом деле, как только "рецепт" сделан, они, вероятно, больше не нужны.

Во-первых, что делает больше, чем unshare()unshare -r? Без этого новый пользователь остается на nobodyи даже не может писать как его первоначальный пользователь:

$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ strace unshare -r -n /bin/sleep 1 2>&1 |sed -n '/^unshare/,/^execve/p'
unshare(CLONE_NEWNET|CLONE_NEWUSER)     = 0
open("/proc/self/setgroups", O_WRONLY)  = 3
write(3, "deny", 4)                     = 4
close(3)                                = 0
open("/proc/self/uid_map", O_WRONLY)    = 3
write(3, "0 1000 1", 8)                 = 8
close(3)                                = 0
open("/proc/self/gid_map", O_WRONLY)    = 3
write(3, "0 1000 1", 8)                 = 8
close(3)                                = 0
execve("/bin/sleep", ["/bin/sleep", "1"], [/* 18 vars */]) = 0

Это будет использовано позже.

$ ip -4 -br a
lo               UNKNOWN        127.0.0.1/8 
eth0@if19        UP             10.0.3.66/24 
$ ping -c1 10.0.3.1
PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.167 ms

--- 10.0.3.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 0.167/0.167/0.167/0.000 ms
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ echo $$
338
$

На другом терминале:

$ gdb --pid=338
Reading symbols from /bin/bash...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libtinfo.so.5...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libdl.so.2...Reading symbols from /usr/lib/debug/.build-id/b8/95f0831f623c5f23603401d4069f9f94c24761.debug...done.
done.
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug/.build-id/aa/889e26a70f98fa8d230d088f7cc5bf43573163.debug...done.
done.

[...]

(gdb)

Теперь вызовем первую функцию:

(gdb) call unshare(CLONE_NEWNET|CLONE_NEWUSER)
No symbol "CLONE_NEWNET" in current context.

Хорошо, может быть способ, чтобы gdb узнал об этом, но я не гуру:

(gdb) !
$ grep CLONE_NEW /usr/include/linux/sched.h # man 2 unshare
#define CLONE_NEWNS 0x00020000  /* New mount namespace group */
#define CLONE_NEWCGROUP     0x02000000  /* New cgroup namespace */
#define CLONE_NEWUTS        0x04000000  /* New utsname namespace */
#define CLONE_NEWIPC        0x08000000  /* New ipc namespace */
#define CLONE_NEWUSER       0x10000000  /* New user namespace */
#define CLONE_NEWPID        0x20000000  /* New pid namespace */
#define CLONE_NEWNET        0x40000000  /* New network namespace */
$ find /usr/include/ -name fcntl.h |xargs grep O_WRONLY # man 2 open
/usr/include/asm-generic/fcntl.h:#define O_WRONLY   00000001
$ exit
exit
(gdb) call unshare(0x50000000)
$1 = 0
(gdb) call open("/proc/self/setgroups", 1)
$2 = 3
(gdb) call write($2,"deny",4)
$3 = 4
(gdb) call close($2)
$4 = 0
(gdb) call open("/proc/self/uid_map", 1)
$5 = 3
(gdb) call write($5, "0 1000 1", 8)
$6 = 8
(gdb) call close($5)
$7 = 0
(gdb) call open("/proc/self/gid_map", 1)
$8 = 3
(gdb) call write($8, "0 1000 1", 8)
$9 = 8
(gdb) call close($8)
$10 = 0
(gdb) quit
A debugging session is active.

    Inferior 1 [process 338] will be detached.

Quit anyway? (y or n) y
Detaching from program: /bin/bash, process 338

В измененном процессе можно убедиться, что интерфейс eth0исчез:

$ ip -br a
lo               DOWN           127.0.0.1/8 
$ echo $$
338
$ id
uid=0(root) gid=0(root) groupes=0(root)
$ touch /
touch: setting times of '/': Permission denied
$ touch ~/test1
$ ls ~/test1
/home/user/test1
$ ping 10.0.3.1
connect: Network is unreachable

Пути назад нет :новое пользовательское пространство имен не может вернуться к исходному пространству имен. Если процесс выполняется с достаточными привилегиями (, например, root без потерянных возможностей или SELinux ), тогда (можно было бы использовать только unshare(CLONE_NEWNET)/setns(savedopenedfd)).

Конечно, это можно записать в файл и изменить любой разрешенный запущенный процесс или изменить саму оболочку из подпроцесса gdb. Содержимое removenetwork.gdb, действительно здесь только для изменения процесса с pid:gid==1000:1000:

ОБНОВЛЕНИЕ :добавлен (приблизительный )тип возвращаемого значения для системных вызовов ниже, это должно избежать некоторых версий gdb для жалоб в средах, отличных от -dev:

call (int)unshare(0x50000000)
call (int)open("/proc/self/setgroups", 1)
call (long)write($2,"deny",4)
call (int)close($2)
call (int)open("/proc/self/uid_map", 1)
call (long)write($5, "0 1000 1", 8)
call (int)close($5)
call (int)open("/proc/self/gid_map", 1)
call (long)write($8, "0 1000 1", 8)
call (int)close($8)
quit

Пример:

$ sh -c 'id; gdb --pid=$$ < removenetwork.gdb >/dev/null 2>&1; id; curl unix.stackexchange.com'
uid=1000(user) gid=1000(user) groups=1000(user)
uid=0(root) gid=0(root) groups=0(root)
curl: (6) Could not resolve host: unix.stackexchange.com

ОБНОВЛЕНИЕ:если корень вообще не нужен, как это видно из этого Вопроса, то нет необходимости сопоставлять с корнем вообще.Просто замените вхождения write($XX, "0 1000 1", 8)наwrite($XX, "1000 1000 1", 11)(для случая uid:gid== 1000:1000). Дополнительные группы по-прежнему неизбежно теряются, но uid/gid не меняется (и отображается сам на себя ).

1
09.08.2020, 19:45
1 ответ

Это будет работать с использованием любого awk в любой оболочке на каждом поле UNIX, даже если все ваши входные значения отрицательные и/или ваш ввод не является точным кратным 10 строкам и независимо от того, сколько пустых строк находится между вашей строкой заголовка и ваши данные:

$ cat tst.awk
NR==1 { print; next }
!NF { next }
(++numLines) % 10 == 1 {
    printf "%s", maxLine
    maxVal = $5
    maxLine = ""
}
$5 >= maxVal {
    maxVal = $5
    maxLine = $0 ORS
}
END { printf "%s", maxLine }

.

$ awk -f tst.awk file
Name      No.           Value1   Value2   Determine
10_M62    6:            3.0561   405.69   1.1824
11_M63    2:            2.3544   526.62   1.8099
4
18.03.2021, 23:14

Теги

Похожие вопросы