LINUX.ORG.RU

Как перехватить сигнал дочернего процесса не используя ptrace?

 , , , ,


0

1

Передо мной стоит задача: Ловить сигнал SIGXCPU потомка, который запускает мой процесс, я для этого использовал ptrace, однако столкнулся с проблемой: При выполнении execve вместе с ptrace capabilities дочернего процесса обнуляются. А они ему тоже нужны.

Вот мой пост с описанием проблемы: Проблема с capabilities и exec (комментарий)

Как всё таки перехватить SIGXCPU потомка так, чтобы ничего не ломалось?


Скорее всего никак. Суть в том же: у него повышенные привилегии, а ты хочешь извне как-то подменить часть его работы (обработку сигнала). Что, теоретически, может использоваться для какого-нить эксплойта. Допиши в потомка обработку этого сигнала и чтоб он родителя сам оповещал об этом.

Ну либо родителя запускай как рута, но это испортит твои планы на безопасность я так понимаю.

firkax ★★★★★
()
Ответ на: комментарий от OlegUP

я про это

Допиши в потомка обработку этого сигнала и чтоб он родителя сам оповещал об этом.

либо в родителе жди waitpid + WIFSIGNALED + WTERMSIG

anonymous2 ★★★★★
()
Последнее исправление: anonymous2 (всего исправлений: 1)

Догуглился + дочитался исходников до такой вещи как LSM (Linux Security Modules Framework)

Есть прога, которая с ним работает, и судя по документации можно настраивать поведение ядра в политике безопасности через хуки)

Вот пример из программы lsmtrace: https://github.com/lumontec/lsmtrace/tree/master

SEC("lsm/bprm_creds_from_file")
int BPF_PROG(bprm_creds_from_file, struct linux_binprm *bprm, struct file *file)
{
	FILTER_CATHEGORY_INT(PROG_EXEC_CATH)
	FILTER_OWN_PID_INT()
	DUMP_FUNC(bprm_creds_from_file, struct linux_binprm *bprm, struct file *file)

	DUMP_LINUX_BINPRM_STRUCT(bprm)
	DUMP_FILE_STRUCT(file)

	bpf_printk("lsm_hook: exec: bprm_creds_from_file\n");
	return 0;
}

Пока копаю в эту сторону, видимо этот хук и нужен.

Что можете сказать по этому поводу?

OlegUP
() автор топика
Ответ на: комментарий от seiken

Было бы так просто, врядли начальство одобрит вшивать эти модули в ядро, а по другому нельзя.

а так да, можно и их заюзать, если готовы потратить время на написание LSM модуля и есть возможность добавить это в ядро.

OlegUP
() автор топика
Последнее исправление: OlegUP (всего исправлений: 2)

можно копнуть не в связку fork+exec для создания процесса, а clone+ldload

во втором случае можно более заковыристо играть флагами и указать что наследуется, а что нет.

в результате не уверен, но копать можно :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Не выйдет наверное, я нашел функцию в ядре, которая сравнивает и выдаёт cap’ы. Такой кусок кода в функции int cap_bprm_creds_from_file(struct linux_binprm *bprm, const struct file *file):

https://elixir.bootlin.com/linux/v6.13.5/source/security/commoncap.c#L918

	if ((is_setid || __cap_gained(permitted, new, old)) &&
	    ((bprm->unsafe & ~LSM_UNSAFE_PTRACE) ||
	     !ptracer_capable(current, new->user_ns))) {
		/* downgrade; they get no more than they had, and maybe less */
		if (!ns_capable(new->user_ns, CAP_SETUID) ||
		    (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) {
			new->euid = new->uid;
			new->egid = new->gid;
		}
		new->cap_permitted = cap_intersect(new->cap_permitted,
						   old->cap_permitted);
	}

Почитав код можно понять, что в предыдущем посте комментаторы были абсолютно правы, ядро не дает трассировать трэйсеру не позволенные ему capabilities у трейси.

OlegUP
() автор топика
Последнее исправление: OlegUP (всего исправлений: 1)

Решили с начальством что будем выдавать myctl – родительскому процессу те же capabilities и не париться.

В итоге решения вопроса поста по состоянию на 2025 год (по одному из):

  • Использовать IPC, если подходит под решение, у этого свои нюансы.
  • Писать LSM модуль и линковать с ядром, со всеми вытекающими сложностями.
  • Выдать родителю те же capabilities, что и потомку, тут вы жертвуете безопасностью.

Задачу помечаю как решенную.

OlegUP
() автор топика
Последнее исправление: OlegUP (всего исправлений: 1)
Ответ на: комментарий от OlegUP

Выдать родителю те же capabilities, что и потомку, тут вы жертвуете безопасностью.

можно ещё сделать мост-супервизор, который запускает и трейсит «потомка», понижает допуски и запускает «родителя». Транслирует родителю SIGXCPU потомка на своём птичьем протоколе.

всё «не-безопасное» будет в супервизоре но он маленький и всё прочее ему можно зарезать.

или пересмотреть вообще использование SIGXCPU - то есть необходимость самого трейса. Вполне вероятно что исходная цель может быть достигнута без него

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)

Чисто теоретически, если код потомка нельзя изменить и если используется fork + exec, то почему бы не воспользоваться LD_PRELOAD при выполнении exec?

Перехватить signal/sigaction и сначала выполнять свой обработчик, а потом уже потомка.

vel ★★★★★
()