Summary: | fakeroot: неопределённое поведение в обёртке syscall | ||
---|---|---|---|
Product: | Sisyphus | Reporter: | Alexey Sheplyakov <asheplyakov> |
Component: | fakeroot | Assignee: | placeholder <placeholder> |
Status: | CLOSED NOTABUG | QA Contact: | qa-sisyphus |
Severity: | normal | ||
Priority: | P5 | CC: | glebfm, ilyakurdyukov, imz, iv, ldv, mike, nir, placeholder, sin |
Version: | unstable | ||
Hardware: | all | ||
OS: | Linux |
Description
Alexey Sheplyakov
2023-04-03 10:59:53 MSK
(In reply to Alexey Sheplyakov from comment #0) > Из-за этого нельзя просто так взять и достать 6 аргументов. Что значит нельзя? Если достать больше аргументов, чем было передано, то будет обычный trash in - garbage out, что вполне подходит для этой обёртки. > 1) Сделать обёртку, которая принимает аргумент va_list (наподобие vprintf) > 2) Понять, сколько их было передано на самом деле исходя из номера > системного вызова (аналогично тому, как printf определяет количество > аргументов из форматной строки) > 3) Перехватывать собственно системный вызов подобно fakeroot-ng (или более > "современным" способом с seccomp filter, примерно так: > https://github.com/alfonsosanchezbeato/ptrace-redirect/blob/master/ > redir_filter.c) > 4) Придумать что-то другое Зачем так усложнять в данном конкретном случае? (Ответ для Dmitry V. Levin на комментарий #1) > (In reply to Alexey Sheplyakov from comment #0) > > Из-за этого нельзя просто так взять и достать 6 аргументов. > > Что значит нельзя? Если достать больше аргументов, чем было передано, то > будет обычный trash in - garbage out, что вполне подходит для этой обёртки. Undefined behavior не подходит никогда. > > 1) Сделать обёртку, которая принимает аргумент va_list (наподобие vprintf) Ничего сложного в этом нет > Зачем так усложнять в данном конкретном случае? Зачем делать плохо, если можно сделать хорошо, и это несложно? (In reply to Alexey Sheplyakov from comment #2) > (Ответ для Dmitry V. Levin на комментарий #1) > > (In reply to Alexey Sheplyakov from comment #0) > > > Из-за этого нельзя просто так взять и достать 6 аргументов. > > > > Что значит нельзя? Если достать больше аргументов, чем было передано, то > > будет обычный trash in - garbage out, что вполне подходит для этой обёртки. > > Undefined behavior не подходит никогда. Это UB только теоретически. > > > 1) Сделать обёртку, которая принимает аргумент va_list (наподобие vprintf) > > Ничего сложного в этом нет Сигнатура syscall() фиксирована и поменять её нельзя. Честно говоря, я тут не вижу несложного решения. > > Зачем так усложнять в данном конкретном случае? > > Зачем делать плохо, если можно сделать хорошо, и это несложно? Мы же не академический институт, зачем нам тут решать чисто теоретические задачи? Думаю, что ничего страшного не происходит от того, что берётся больше аргументов, чем было на самом деле передано (и чем ожидает на самом деле конкретный системный вызов), ведь даже в реализациях syscall.S в glibc тупо загружают для системного вызова максимум аргументов вне зависимости от конкретного вызова. Т.е. эту задачу не пытаются решить. (Только для ia64 по-хитрому сдвигают номера регистров, как я понял, но хоть архитектура и очень похожа на e2k, соглашение о вызове variadic function на e2k другое и ведёт к тому, что аргументы в памяти, а не в регистрах, и так сделать нельзя.) # tail -n20 glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/*/syscall.S ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/aarch64/syscall.S <== For kernel entry we need to move the system call nr to x8 then load the remaining arguments to register. */ ENTRY (syscall) uxtw x8, w0 mov x0, x1 mov x1, x2 mov x2, x3 mov x3, x4 mov x4, x5 mov x5, x6 mov x6, x7 svc 0x0 cmn x0, #4095 b.cs 1f RET 1: b SYSCALL_ERROR PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/alpha/syscall.S <== .prologue 1 #else .prologue 0 #endif mov a0, v0 /* Syscall number -> v0 */ mov a1, a0 /* arg1-arg5 -> a0-a4 */ mov a2, a1 mov a3, a2 mov a4, a3 mov a5, a4 ldq a5,0(sp) /* arg6 -> a5 */ call_pal PAL_callsys /* Invoke system call */ bne a3, SYSCALL_ERROR_LABEL ret PSEUDO_END(__syscall) weak_alias (__syscall, syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/arm/syscall.S <== cfi_rel_offset (r5, 4) cfi_rel_offset (r6, 8) cfi_rel_offset (r7, 12) mov r7, r0 mov r0, r1 mov r1, r2 mov r2, r3 ldmfd ip, {r3, r4, r5, r6} swi 0x0 pop {r4, r5, r6, r7} cfi_adjust_cfa_offset (-16) cfi_restore (r4) cfi_restore (r5) cfi_restore (r6) cfi_restore (r7) cmn r0, #4096 it cc RETINSTR(cc, lr) b PLTJMP(syscall_error) PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/e2k/syscall.S <== setwd wsz = 0x9 setbn rsz = 0x3, rbs = 0x5, rcur = 0x0 getsp 0x0, %r7 __SYSCALL_ARG_MEM (%r7, 0x0, %b[0]) __SYSCALL_ARG_MEM (%r7, 0x8, %b[1]) __SYSCALL_ARG_MEM (%r7, 0x10, %b[2]) __SYSCALL_ARG_MEM (%r7, 0x18, %b[3]) __SYSCALL_ARG_MEM (%r7, 0x20, %b[4]) __SYSCALL_ARG_MEM (%r7, 0x28, %b[5]) __SYSCALL_ARG_MEM (%r7, 0x30, %b[6]) sdisp %ctpr1, __SYSCALL_TRAPNUM call %ctpr1, wbs = 0x5 __SYSCALL_OUTPUT ret PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/i386/syscall.S <== <http://www.gnu.org/licenses/>. */ #include <sysdep.h> /* Please consult the file sysdeps/unix/sysv/linux/i386/sysdep.h for more information about the value -4095 used below.*/ .text ENTRY (syscall) PUSHARGS_6 /* Save register contents. */ _DOARGS_6(44) /* Load arguments. */ movl 20(%esp), %eax /* Load syscall number into %eax. */ ENTER_KERNEL /* Do the system call. */ POPARGS_6 /* Restore register contents. */ cmpl $-4095, %eax /* Check %eax for error. */ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ ret /* Return to caller. */ PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/ia64/syscall.S <== You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ #include <sysdep.h> ENTRY(syscall) /* We are called like so: {out0,out1,...,out6} registers -> {NR, arg1, ..., arg6} Shift the register window so that {out1...out6} are available in {out0...out5} like the kernel syscall handler expects. */ alloc r2=ar.pfs,1,0,8,0 mov r15=r32 /* syscall number */ break __BREAK_SYSCALL ;; cmp.ne p6,p0=-1,r10 /* r10 = -1 on error */ (p6) ret br.cond.spnt.few __syscall_error PSEUDO_END(syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/m68k/syscall.S <== You should have received a copy of the GNU Lesser General Public License along with the GNU C Library. If not, see <http://www.gnu.org/licenses/>. */ #include <sysdep.h> /* Please consult the file sysdeps/unix/sysv/linux/m68k/sysdep.h for more information about the value -4095 used below.*/ .text ENTRY (syscall) move.l 4(%sp), %d0 /* Load syscall number. */ _DOARGS_6 (28) /* Frob arguments. */ trap &0 /* Do the system call. */ UNDOARGS_6 /* Unfrob arguments. */ cmp.l &-4095, %d0 /* Check %d0 for error. */ jcc SYSCALL_ERROR_LABEL /* Jump to error handler if negative. */ rts /* Return to caller. */ PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/microblaze/syscall.S <== #include <sysdep.h> .text ENTRY (syscall) addk r12,r0,r5 addk r5,r0,r6 addk r6,r0,r7 addk r7,r0,r8 addk r8,r0,r9 addk r9,r0,r10 lwi r10,r1,28 brki r14,8 addk r0,r0,r0 addik r4,r0,-4095 cmpu r4,r4,r3 bgei r4,SYSCALL_ERROR_LABEL rtsd r15,8 nop PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/nios2/syscall.S <== <http://www.gnu.org/licenses/>. */ #include <sysdep.h> /* We don't need a special syscall to implement syscall(). It won't work reliably with 64-bit arguments (but that is true on many modern platforms). */ ENTRY (syscall) mov r2, r4 mov r4, r5 mov r5, r6 mov r6, r7 ldw r7, 0(sp) ldw r8, 4(sp) ldw r9, 8(sp) trap bne r7, zero, SYSCALL_ERROR_LABEL ret PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/powerpc/syscall.S <== 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 <http://www.gnu.org/licenses/>. */ #include <sysdep.h> ENTRY (syscall) mr r0,r3 mr r3,r4 mr r4,r5 mr r5,r6 mr r6,r7 mr r7,r8 mr r8,r9 sc PSEUDO_RET PSEUDO_END (syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/sh/syscall.S <== mov r7, r6 // p3 mov.l @r15, r7 // p4 mov.l @(4,r15), r0 // p5 mov.l @(8,r15), r1 // p6 mov.l @(12,r15), r2 // p7 trapa #0x17 mov r0, r1 mov #-12, r2 shad r2, r1 not r1, r1 // r1=0 means r0 = -1 to -4095 tst r1, r1 // i.e. error in linux bf .Lpseudo_end SYSCALL_ERROR_HANDLER .Lpseudo_end: rts nop PSEUDO_END (__syscall) weak_alias (__syscall, syscall) ==> glibc-2.29-alt2.E2K.26.012.1/sysdeps/unix/sysv/linux/x86_64/syscall.S <== /* Usage: long syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6) We need to do some arg shifting, the syscall_number will be in rax. */ .text ENTRY (syscall) movq %rdi, %rax /* Syscall number -> rax. */ movq %rsi, %rdi /* shift arg1 - arg5. */ movq %rdx, %rsi movq %rcx, %rdx movq %r8, %r10 movq %r9, %r8 movq 8(%rsp),%r9 /* arg6 is on the stack. */ syscall /* Do the system call. */ cmpq $-4095, %rax /* Check %rax for error. */ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ ret /* Return to caller. */ PSEUDO_END (syscall) > Это UB только теоретически. Проявлений на практике не было описано. Исправлять не надо,... > ведь даже в реализациях syscall.S в glibc тупо загружают для системного вызова максимум аргументов вне зависимости от конкретного вызова. Т.е. эту задачу не пытаются решить. |