writev() system call causing segmentation fault with invalid vector
shaikshavali1 opened this issue · 3 comments
Original Test case writev02:
The file is created and write() is called with valid buffer to write
at some 8k th offset. After that writev() will be called with invalid
vector. This should return EFAULT. And at the same time, try looking at
the 8kth offset whether the file is intact or not.
Problem: if invalid vector is passed to the writev syscall expected to return EFAULT. But it is causing segmentation fault.
[[ SGX-LKL ]] libc_start_main_stage2(): Calling app main: /ltp/testcases/kernel/syscalls/writev/writev02
writev02 0 TINFO : Enter block 1
[[ SIGNAL ]] Exception SIGSEGV (page fault) received (code=5 address=0x7fb000218fb8 opcode=0xb60f)
[[ SGX-LKL ]] #0: 7fb0000e1bb2 in generic_perform_write(...)
[[ SGX-LKL ]] #1: 7fb0000e1e08 in __generic_file_write_iter(...)
[[ SGX-LKL ]] #2: 7fb0000e1fd3 in generic_file_write_iter(...)
[[ SGX-LKL ]] #3: 7fb000107c5a in do_iter_readv_writev(...)
[[ SGX-LKL ]] #4: 7fb000108446 in do_iter_write(...)
[[ SGX-LKL ]] #5: 7fb0001084f0 in vfs_writev(...)
[[ SGX-LKL ]] #6: 7fb0001085f6 in do_writev(...)
[[ SGX-LKL ]] #7: 7fb00010936b in __se_sys_writev(...)
[[ SGX-LKL ]] #8: 7fb00008b86f in lkl_syscall(...)
[[ SGX-LKL ]] #9: 7fb0005a5179 in __filter_syscall3(...)
[[ SGX-LKL ]] #10: 7fb0005a51b1 in writev(...)
[[ SGX-LKL ]] #11: 7fb03da5b782 in <unknown>(...)
writev02 1 TBROK : writev02.c:218: sighandler received invalid signal : 11
bad count while changing owner
[[ SGX-LKL ]] FAIL: Kernel panic! Aborting...
GDB logs:
Thread 6 "ENCLAVE" hit Breakpoint 2, do_writev (fd=<optimized out>, vec=0x7fe03dc75040 <wr_iovec>, vlen=2, flags=0) at fs/read_write.c:1052
1052 if (f.file) {
(gdb) bt
#0 do_writev (fd=<optimized out>, vec=0x7fe03dc75040 <wr_iovec>, vlen=2, flags=0) at fs/read_write.c:1052
#1 0x00007fe00010936b in __do_sys_writev (vlen=<optimized out>, vec=<optimized out>, fd=<optimized out>) at fs/read_write.c:1131
#2 __se_sys_writev (fd=<optimized out>, vec=<optimized out>, vlen=<optimized out>) at fs/read_write.c:1128
#3 0x00007fe00008b86f in run_syscall (params=<optimized out>, no=<optimized out>) at arch/lkl/kernel/syscalls.c:44
#4 lkl_syscall (no=2, params=0x7fe040b02e30) at arch/lkl/kernel/syscalls.c:192
#5 0x00007fe0005a5179 in __filter_syscall3 (n=66, a1=4, a2=140601085874240, a3=2) at ./src/internal/syscall.h:81
#6 0x00007fe0005a51b1 in writev (fd=4, iov=0x7fe03dc75040 <wr_iovec>, count=2) at src/unistd/writev.c:6
#7 0x00007fe03da5b782 in main (argc=<optimized out>, argv=<optimized out>) at writev02.c:149
#8 0x00007fe000532904 in libc_start_main_stage2 (main=0x7fe03da5b590 <main>, argc=1, argv=0x7fe040b02f70) at src/env/__libc_start_main.c:168
#9 0x00007fe00053285e in __libc_start_main (main=0x7fe03da5b590 <main>, argc=1, argv=0x7fe040b02f70) at src/env/__libc_start_main.c:153
#10 0x00007fe03da5b9eb in _start_c (p=<optimized out>) at crt/crt1.c:17
#11 0x00007fe03da5b9c3 in _start ()
#12 0x00007fe040b03120 in ?? ()
#13 0x0000000000000001 in ?? ()
#14 0x00007fe000b04860 in ?? ()
#15 0x0000000000000000 in ?? ()
(gdb) s
1053 loff_t pos, *ppos = file_ppos(f.file);
(gdb) s
file_ppos (file=<optimized out>) at fs/read_write.c:573
573 return file->f_mode & FMODE_STREAM ? NULL : &file->f_pos;
(gdb) s
do_writev (fd=<optimized out>, vec=0x7fe03dc75040 <wr_iovec>, vlen=2, flags=0) at fs/read_write.c:1055
1055 pos = *ppos;
(gdb) s
1058 ret = vfs_writev(f.file, vec, vlen, ppos, flags);
(gdb) s
1055 pos = *ppos;
(gdb) s
1058 ret = vfs_writev(f.file, vec, vlen, ppos, flags);
(gdb) s
vfs_writev (file=0x7fe03e88be00, vec=0x7fe03dc75040 <wr_iovec>, vlen=2, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:1012
1012 ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
(gdb) s
1006 {
(gdb) s
1008 struct iovec *iov = iovstack;
(gdb) s
1006 {
(gdb) s
1012 ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
(gdb) s
1006 {
(gdb) s
1012 ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
(gdb) s
1008 struct iovec *iov = iovstack;
(gdb) s
1012 ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
(gdb) s
import_iovec (type=1, uvector=0x7fe03dc75040 <wr_iovec>, nr_segs=2, fast_segs=8, iov=0x7fe040b02c68, i=0x7fe040b02c70) at lib/iov_iter.c:1642
1642 {
(gdb) s
1645 n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
(gdb) s
1642 {
(gdb) s
import_iovec (type=1, uvector=0x7fe03dc75040 <wr_iovec>, nr_segs=2, fast_segs=8, iov=0x7fe040b02c68, i=0x7fe040b02c70) at lib/iov_iter.c:1645
1645 n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
(gdb) s
1642 {
(gdb) s
import_iovec (type=1, uvector=0x7fe03dc75040 <wr_iovec>, nr_segs=<optimized out>, fast_segs=8, iov=0x7fe040b02c68, i=0x7fe040b02c70)
at lib/iov_iter.c:1645
1645 n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
(gdb) s
rw_copy_check_uvector (type=1, uvector=0x7fe03dc75040 <wr_iovec>, nr_segs=2, fast_segs=8, fast_pointer=0x7fe040b02ca0, ret_pointer=0x7fe040b02c08)
at fs/read_write.c:779
779 ret = 0;
(gdb) s
768 {
(gdb) s
778 if (nr_segs == 0) {
(gdb) s
768 {
(gdb) s
778 if (nr_segs == 0) {
(gdb) s
787 if (nr_segs > UIO_MAXIOV) {
(gdb) s
791 if (nr_segs > fast_segs) {
(gdb) s
798 if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
(gdb) s
copy_from_user (n=<optimized out>, from=<optimized out>, to=<optimized out>) at ./include/linux/uaccess.h:144
144 n = _copy_from_user(to, from, n);
(gdb) s
_copy_from_user (to=0x7fe040b02ca0, from=0x7fe03dc75040 <wr_iovec>, n=32) at lib/usercopy.c:11
11 if (likely(access_ok(from, n))) {
(gdb) s
__lkl_access_ok (size=<optimized out>, addr=<optimized out>) at ./arch/lkl/include/asm/uaccess.h:14
14 if ( lkl_access_ok ) ret = lkl_access_ok(addr, size);
(gdb) s
lkl_access_ok (addr=140601085874240, size=32) at lkl/setup.c:1548
1548 int ret = 1;
(gdb) s
1551 if (!size)
(gdb) s
1554 ret = oe_is_within_enclave((void*)addr, size);
(gdb) s
oe_is_within_enclave (p=0x7fe03dc75040 <wr_iovec>, n=32) at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/memory.c:9
9 uint64_t range_start = (uint64_t)p;
(gdb) s
10 uint64_t range_end = range_start + (n == 0 ? 1 : n);
(gdb) s
11 uint64_t enclave_start = (uint64_t)__oe_get_enclave_base();
(gdb) s
__oe_get_enclave_base () at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/globals.c:145
145 return (uint8_t*)&_enclave_rva - _enclave_rva;
(gdb) s
oe_is_within_enclave (p=0x7fe03dc75040 <wr_iovec>, n=32) at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/memory.c:12
12 uint64_t enclave_end = enclave_start + __oe_get_enclave_size();
(gdb) s
__oe_get_enclave_size () at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/globals.c:150
150 return oe_enclave_properties_sgx.image_info.enclave_size;
(gdb) s
oe_is_within_enclave (p=0x7fe03dc75040 <wr_iovec>, n=32) at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/memory.c:16
16 if ((range_start > 0) && (range_end > range_start) &&
(gdb) s
17 (enclave_end > enclave_start) &&
(gdb) s
18 ((range_start >= enclave_start) && (range_end <= enclave_end)))
(gdb) s
16 if ((range_start > 0) && (range_end > range_start) &&
(gdb) s
20 return true;
(gdb) s
24 }
(gdb) s
lkl_access_ok (addr=140601085874240, size=32) at lkl/setup.c:1555
1555 if (!ret)
(gdb) s
1559 return ret;
(gdb) s
1560 }
(gdb) s
_copy_from_user (to=0xffffffffff558b88, from=0x0, n=32) at lib/usercopy.c:11
11 if (likely(access_ok(from, n))) {
(gdb) s
13 res = raw_copy_from_user(to, from, n);
(gdb) s
raw_copy_from_user (n=<optimized out>, from=<optimized out>, to=<optimized out>) at ./arch/lkl/include/asm/uaccess.h:43
43 memcpy(to, (const void __force *)from, n);
(gdb) s
memcpy (dest=0x7fe040b02ca0, src=0x7fe03dc75040 <wr_iovec>, count=32) at lib/string.c:847
847 {
(gdb) s
851 while (count--)
(gdb) s
847 {
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb) s
851 while (count--)
(gdb) s
852 *tmp++ = *s++;
(gdb)
851 while (count--)
(gdb)
852 *tmp++ = *s++;
(gdb)
851 while (count--)
(gdb)
852 *tmp++ = *s++;
(gdb)
851 while (count--)
(gdb)
852 *tmp++ = *s++;
(gdb)
(gdb)
851 while (count--)
(gdb)
854 }
(gdb)
_copy_from_user (to=0x7fe040b02ca0, from=0x7fe03dc75040 <wr_iovec>, n=32) at lib/usercopy.c:18
18 }
(gdb)
13 res = raw_copy_from_user(to, from, n);
(gdb)
18 }
(gdb)
rw_copy_check_uvector (type=1, uvector=0x7fe03dc75040 <wr_iovec>, nr_segs=<optimized out>, fast_segs=<optimized out>, fast_pointer=<optimized out>,
ret_pointer=<optimized out>) at fs/read_write.c:798
798 if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
(gdb)
812 ret = 0;
(gdb)
828 if (len > MAX_RW_COUNT - ret) {
(gdb)
815 ssize_t len = (ssize_t)iov[seg].iov_len;
(gdb)
819 if (len < 0) {
(gdb)
815 ssize_t len = (ssize_t)iov[seg].iov_len;
(gdb)
819 if (len < 0) {
(gdb)
823 if (type >= 0
(gdb)
824 && unlikely(!access_ok(buf, len))) {
(gdb)
__lkl_access_ok (size=<optimized out>, addr=<optimized out>) at ./arch/lkl/include/asm/uaccess.h:14
14 if ( lkl_access_ok ) ret = lkl_access_ok(addr, size);
(gdb)
lkl_access_ok (addr=140601083650048, size=8192) at lkl/setup.c:1548
1548 int ret = 1;
(gdb)
1551 if (!size)
(gdb)
1554 ret = oe_is_within_enclave((void*)addr, size);
(gdb)
oe_is_within_enclave (p=0x7fe03da56000, n=8192) at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/memory.c:9
9 uint64_t range_start = (uint64_t)p;
(gdb)
10 uint64_t range_end = range_start + (n == 0 ? 1 : n);
(gdb)
11 uint64_t enclave_start = (uint64_t)__oe_get_enclave_base();
(gdb)
__oe_get_enclave_base () at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/globals.c:145
145 return (uint8_t*)&_enclave_rva - _enclave_rva;
(gdb)
oe_is_within_enclave (p=0x7fe03da56000, n=8192) at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/memory.c:12
12 uint64_t enclave_end = enclave_start + __oe_get_enclave_size();
(gdb)
__oe_get_enclave_size () at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/globals.c:150
150 return oe_enclave_properties_sgx.image_info.enclave_size;
(gdb)
oe_is_within_enclave (p=0x7fe03da56000, n=8192) at /mnt/shaik/1108/sgx-lkl/openenclave/enclave/core/sgx/memory.c:16
16 if ((range_start > 0) && (range_end > range_start) &&
(gdb)
17 (enclave_end > enclave_start) &&
(gdb)
18 ((range_start >= enclave_start) && (range_end <= enclave_end)))
(gdb)
16 if ((range_start > 0) && (range_end > range_start) &&
(gdb)
20 return true;
(gdb)
24 }
(gdb)
lkl_access_ok (addr=140601083650048, size=8192) at lkl/setup.c:1555
1555 if (!ret)
(gdb)
1559 return ret;
(gdb)
1560 }
(gdb)
rw_copy_check_uvector (type=1, uvector=<optimized out>, nr_segs=<optimized out>, fast_segs=<optimized out>, fast_pointer=<optimized out>,
ret_pointer=<optimized out>) at fs/read_write.c:824
824 && unlikely(!access_ok(buf, len))) {
(gdb)
832 ret += len;
(gdb)
813 for (seg = 0; seg < nr_segs; seg++) {
(gdb)
815 ssize_t len = (ssize_t)iov[seg].iov_len;
(gdb)
819 if (len < 0) {
(gdb)
815 ssize_t len = (ssize_t)iov[seg].iov_len;
(gdb)
819 if (len < 0) {
(gdb)
823 if (type >= 0
(gdb)
824 && unlikely(!access_ok(buf, len))) {
(gdb)
__lkl_access_ok (size=<optimized out>, addr=<optimized out>) at ./arch/lkl/include/asm/uaccess.h:14
14 if ( lkl_access_ok ) ret = lkl_access_ok(addr, size);
(gdb)
lkl_access_ok (addr=0, size=0) at lkl/setup.c:1548
1548 int ret = 1;
(gdb)
1551 if (!size)
(gdb)
1552 return ret;
(gdb)
1560 }
(gdb)
rw_copy_check_uvector (type=1, uvector=<optimized out>, nr_segs=<optimized out>, fast_segs=<optimized out>, fast_pointer=<optimized out>,
ret_pointer=<optimized out>) at fs/read_write.c:824
824 && unlikely(!access_ok(buf, len))) {
(gdb)
832 ret += len;
(gdb)
813 for (seg = 0; seg < nr_segs; seg++) {
(gdb)
835 *ret_pointer = iov;
(gdb)
837 }
(gdb)
import_iovec (type=1, uvector=<optimized out>, nr_segs=<optimized out>, fast_segs=<optimized out>, iov=0x7fe040b02c68, i=0x7fe040b02c70)
at lib/iov_iter.c:1647
1647 if (n < 0) {
(gdb)
1645 n = rw_copy_check_uvector(type, uvector, nr_segs, fast_segs,
(gdb)
1647 if (n < 0) {
(gdb)
1653 iov_iter_init(i, type, p, nr_segs, n);
(gdb)
iov_iter_init (i=0x7fe040b02c70, direction=1, iov=0x7fe040b02ca0, nr_segs=2, count=8192) at lib/iov_iter.c:440
440 WARN_ON(direction & ~(READ | WRITE));
(gdb)
444 if (uaccess_kernel()) {
(gdb)
441 direction &= READ | WRITE;
(gdb)
444 if (uaccess_kernel()) {
(gdb)
448 i->type = ITER_IOVEC | direction;
(gdb)
449 i->iov = iov;
(gdb)
448 i->type = ITER_IOVEC | direction;
(gdb)
451 i->nr_segs = nr_segs;
(gdb)
452 i->iov_offset = 0;
(gdb)
453 i->count = count;
(gdb)
454 }
(gdb)
import_iovec (type=1, uvector=<optimized out>, nr_segs=<optimized out>, fast_segs=<optimized out>, iov=0x7fe040b02c68, i=0x7fe040b02c70)
at lib/iov_iter.c:1654
1654 *iov = p == *iov ? NULL : p;
(gdb)
1655 return n;
(gdb)
1656 }
(gdb)
vfs_writev (file=0x7fe03e88be00, vec=<optimized out>, vlen=<optimized out>, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:1013
1013 if (ret >= 0) {
(gdb)
1014 file_start_write(file);
(gdb)
file_start_write (file=<optimized out>) at fs/read_write.c:1014
1014 file_start_write(file);
(gdb)
file_inode (f=<optimized out>) at ./include/linux/fs.h:1300
1300 return f->f_inode;
(gdb)
file_start_write (file=<optimized out>) at ./include/linux/fs.h:2826
2826 if (!S_ISREG(file_inode(file)->i_mode))
(gdb)
vfs_writev (file=0x7fe03e88be00, vec=<optimized out>, vlen=<optimized out>, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:1014
1014 file_start_write(file);
(gdb)
file_start_write (file=<optimized out>) at ./include/linux/fs.h:2828
2828 __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
(gdb)
__sb_start_write (sb=0x7fe03fec7000, level=1, wait=true) at fs/super.c:1520
1520 {
(gdb)
__sb_start_write (sb=0x7fe03fec7000, level=1, wait=true) at fs/super.c:1544
1544 if (wait && !force_trylock)
(gdb)
1545 percpu_down_read(sb->s_writers.rw_sem + level-1);
(gdb)
percpu_down_read (sem=<optimized out>) at ./include/linux/percpu-rwsem.h:51
51 __this_cpu_inc(*sem->read_count);
(gdb)
52 if (unlikely(!rcu_sync_is_idle(&sem->rss)))
(gdb)
rcu_sync_is_idle (rsp=<optimized out>) at ./include/linux/percpu-rwsem.h:52
52 if (unlikely(!rcu_sync_is_idle(&sem->rss)))
(gdb)
__read_once_size (size=<optimized out>, res=<optimized out>, p=<optimized out>) at ./include/linux/compiler.h:199
199 __READ_ONCE_SIZE;
(gdb)
percpu_down_read (sem=<optimized out>) at ./include/linux/percpu-rwsem.h:52
52 if (unlikely(!rcu_sync_is_idle(&sem->rss)))
(gdb)
__sb_start_write (sb=<optimized out>, level=1, wait=true) at fs/super.c:1522
1522 int ret = 1;
(gdb)
1551 }
(gdb)
vfs_writev (file=0x7fe03e88be00, vec=<optimized out>, vlen=<optimized out>, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:1015
1015 ret = do_iter_write(file, &iter, pos, flags);
(gdb)
(gdb)
do_iter_write (file=0x7fe03e88be00, iter=0x7fe040b02c70, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:957
957 if (!(file->f_mode & FMODE_WRITE))
(gdb)
959 if (!(file->f_mode & FMODE_CAN_WRITE))
(gdb)
962 tot_len = iov_iter_count(iter);
(gdb)
iov_iter_count (i=<optimized out>) at ./include/linux/uio.h:235
235 return i->count;
(gdb)
do_iter_write (file=0x7fe03e88be00, iter=0x7fe040b02c70, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:963
963 if (!tot_len)
(gdb)
965 ret = rw_verify_area(WRITE, file, pos, tot_len);
(gdb)
rw_verify_area (read_write=1, file=0x7fe03e88be00, ppos=0x7fe040b02d68, count=8192) at fs/read_write.c:372
372 return retval;
(gdb)
366 {
(gdb)
371 if (unlikely((ssize_t) count < 0))
(gdb)
399 return security_file_permission(file,
(gdb)
378 if (ppos) {
(gdb)
379 loff_t pos = *ppos;
(gdb)
381 if (unlikely(pos < 0)) {
(gdb)
386 } else if (unlikely((loff_t) (pos + count) < 0)) {
(gdb)
370 inode = file_inode(file);
(gdb)
file_inode (f=<optimized out>) at ./include/linux/fs.h:1300
1300 return f->f_inode;
(gdb)
rw_verify_area (read_write=1, file=0x7fe03e88be00, ppos=<optimized out>, count=8192) at fs/read_write.c:399
399 return security_file_permission(file,
(gdb)
391 if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
(gdb)
(gdb)
401 }
(gdb)
do_iter_write (file=0x7fe03e88be00, iter=0x7fe040b02c70, pos=0x7fe040b02d68, flags=0) at fs/read_write.c:966
966 if (ret < 0)
(gdb)
969 if (file->f_op->write_iter)
(gdb)
970 ret = do_iter_readv_writev(file, iter, pos, WRITE, flags);
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:680
680 {
(gdb)
684 init_sync_kiocb(&kiocb, filp);
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at fs/read_write.c:684
684 init_sync_kiocb(&kiocb, filp);
(gdb)
iocb_flags (file=<optimized out>) at ./include/linux/fs.h:3330
3330 int res = 0;
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:680
680 {
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:684
684 init_sync_kiocb(&kiocb, filp);
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at fs/read_write.c:684
684 init_sync_kiocb(&kiocb, filp);
(gdb)
iocb_flags (file=<optimized out>) at ./include/linux/fs.h:3331
3331 if (file->f_flags & O_APPEND)
(gdb)
3330 int res = 0;
(gdb)
3334 res |= IOCB_DIRECT;
(gdb)
3335 if ((file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host))
(gdb)
iocb_flags (file=<optimized out>) at ./include/linux/fs.h:3338
3338 res |= IOCB_SYNC;
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at ./include/linux/fs.h:2042
2042 .ki_hint = ki_hint_validate(file_write_hint(filp)),
(gdb)
file_write_hint (file=<optimized out>) at ./include/linux/fs.h:2020
2020 if (file->f_write_hint != WRITE_LIFE_NOT_SET)
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at ./include/linux/fs.h:2041
2041 .ki_flags = iocb_flags(filp),
(gdb)
iocb_flags (file=<optimized out>) at ./include/linux/fs.h:3338
3338 res |= IOCB_SYNC;
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at ./include/linux/fs.h:2042
2042 .ki_hint = ki_hint_validate(file_write_hint(filp)),
(gdb)
file_write_hint (file=<optimized out>) at ./include/linux/fs.h:2020
2020 if (file->f_write_hint != WRITE_LIFE_NOT_SET)
(gdb)
2023 return file_inode(file)->i_write_hint;
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at ./include/linux/fs.h:2043
2043 .ki_ioprio = get_current_ioprio(),
(gdb)
get_current_ioprio () at ./include/linux/ioprio.h:79
79 struct io_context *ioc = current->io_context;
(gdb)
81 if (ioc)
(gdb)
82 return ioc->ioprio;
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at ./include/linux/fs.h:2039
2039 *kiocb = (struct kiocb) {
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:685
685 ret = kiocb_set_rw_flags(&kiocb, flags);
(gdb)
kiocb_set_rw_flags (flags=<optimized out>, ki=<optimized out>) at ./include/linux/fs.h:3344
3344 if (unlikely(flags & ~RWF_SUPPORTED))
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:684
684 init_sync_kiocb(&kiocb, filp);
(gdb)
init_sync_kiocb (filp=<optimized out>, kiocb=<optimized out>) at ./include/linux/fs.h:2039
2039 *kiocb = (struct kiocb) {
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:685
685 ret = kiocb_set_rw_flags(&kiocb, flags);
(gdb)
kiocb_set_rw_flags (flags=<optimized out>, ki=<optimized out>) at ./include/linux/fs.h:3344
3344 if (unlikely(flags & ~RWF_SUPPORTED))
(gdb)
3347 if (flags & RWF_NOWAIT) {
(gdb)
3352 if (flags & RWF_HIPRI)
(gdb)
3354 if (flags & RWF_DSYNC)
(gdb)
3356 if (flags & RWF_SYNC)
(gdb)
3358 if (flags & RWF_APPEND)
(gdb)
do_iter_readv_writev (filp=0x7fe03e88be00, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:688
688 kiocb.ki_pos = (ppos ? *ppos : 0);
(gdb)
690 if (type == READ)
(gdb)
688 kiocb.ki_pos = (ppos ? *ppos : 0);
(gdb)
691 ret = call_read_iter(filp, &kiocb, iter);
(gdb)
call_read_iter (iter=<optimized out>, kio=<optimized out>, file=<optimized out>) at ./include/linux/fs.h:1864
1864 return file->f_op->read_iter(kio, iter);
(gdb)
do_iter_readv_writev (filp=<optimized out>, iter=0x7fe040b02c70, ppos=0x7fe040b02d68, type=1, flags=0) at fs/read_write.c:690
690 if (type == READ)
(gdb)
693 ret = call_write_iter(filp, &kiocb, iter);
(gdb)
call_write_iter (iter=<optimized out>, kio=<optimized out>, file=<optimized out>) at ./include/linux/fs.h:1870
1870 return file->f_op->write_iter(kio, iter);
(gdb)
generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3482
3482 struct inode *inode = file->f_mapping->host;
(gdb)
3485 inode_lock(inode);
(gdb)
inode_lock (inode=<optimized out>) at ./include/linux/fs.h:778
778 down_write(&inode->i_rwsem);
(gdb)
down_write (sem=0x7fe04009a6e0) at kernel/locking/rwsem.c:1498
1498 {
(gdb)
1501 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
(gdb)
__down_write (sem=<optimized out>) at kernel/locking/rwsem.c:1501
1501 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
(gdb)
atomic_long_try_cmpxchg_acquire (new=<optimized out>, old=<optimized out>, v=<optimized out>) at kernel/locking/rwsem.c:1501
1501 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
(gdb)
atomic64_try_cmpxchg_acquire (new=<optimized out>, old=<optimized out>, v=<optimized out>) at ./include/linux/atomic-fallback.h:2041
2041 r = atomic64_cmpxchg_acquire(v, o, new);
(gdb)
down_write (sem=0x7fe04009a6e0) at kernel/locking/rwsem.c:1498
1498 {
(gdb)
down_write (sem=0x7fe04009a6e0) at kernel/locking/rwsem.c:1501
1501 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
(gdb)
__down_write (sem=<optimized out>) at kernel/locking/rwsem.c:1501
1501 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
(gdb)
atomic_long_try_cmpxchg_acquire (new=<optimized out>, old=<optimized out>, v=<optimized out>) at kernel/locking/rwsem.c:1501
1501 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
(gdb)
atomic64_try_cmpxchg_acquire (new=<optimized out>, old=<optimized out>, v=<optimized out>) at ./include/linux/atomic-fallback.h:2041
2041 r = atomic64_cmpxchg_acquire(v, o, new);
(gdb)
atomic64_cmpxchg (v=0x7fe04009a6e0, o=0, n=1) at lib/atomic64.c:154
154 raw_spin_lock_irqsave(lock, flags);
(gdb)
arch_local_irq_save () at ./include/asm-generic/irqflags.h:29
29 flags = arch_local_save_flags();
(gdb)
arch_local_save_flags () at arch/lkl/kernel/irq.c:166
166 {
(gdb)
167 return irqs_enabled;
(gdb)
166 {
(gdb)
168 }
(gdb)
arch_local_irq_save () at ./include/asm-generic/irqflags.h:30
30 arch_local_irq_restore(ARCH_IRQ_DISABLED);
(gdb) bt
#0 arch_local_irq_save () at ./include/asm-generic/irqflags.h:30
#1 atomic64_cmpxchg (v=0x7fe04009a6e0, o=0, n=1) at lib/atomic64.c:154
#2 0x00007fe0004170b8 in atomic64_try_cmpxchg_acquire (new=<optimized out>, old=<optimized out>, v=<optimized out>)
at ./include/linux/atomic-fallback.h:2041
#3 atomic_long_try_cmpxchg_acquire (new=<optimized out>, old=<optimized out>, v=<optimized out>) at ./include/asm-generic/atomic-long.h:442
#4 __down_write (sem=<optimized out>) at kernel/locking/rwsem.c:1363
#5 down_write (sem=0x7fe04009a6e0) at kernel/locking/rwsem.c:1501
#6 0x00007fe04009a6e0 in ?? ()
#7 0x00007fe040b02bb0 in ?? ()
#8 0x00007fe0000e1ef1 in inode_lock (inode=<optimized out>) at ./include/linux/fs.h:778
#9 generic_file_write_iter (iocb=0x7fe04009a6e0, from=0x0) at mm/filemap.c:3485
#10 0x00007fe040b02c70 in ?? ()
#11 0x00007fe03e88be00 in ?? ()
#12 0x00007fe040b02d68 in ?? ()
#13 0x00007fe040b02c00 in ?? ()
#14 0x00007fe000107c5a in call_write_iter (iter=<optimized out>, kio=<optimized out>, file=<optimized out>) at ./include/linux/fs.h:1870
#15 do_iter_readv_writev (filp=<optimized out>, iter=<optimized out>, ppos=0x1, type=<optimized out>, flags=<optimized out>) at fs/read_write.c:693
#16 0x0000000000000000 in ?? ()
(gdb) s
29 flags = arch_local_save_flags();
(gdb)
30 arch_local_irq_restore(ARCH_IRQ_DISABLED);
(gdb)
arch_local_irq_restore (flags=0) at arch/lkl/kernel/irq.c:172
172 if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED &&
(gdb)
175 irqs_enabled = flags;
(gdb)
atomic64_cmpxchg (v=0x7fe04009a6e0, o=0, n=1) at lib/atomic64.c:155
155 val = v->counter;
(gdb)
156 if (val == o)
(gdb)
157 v->counter = n;
(gdb)
158 raw_spin_unlock_irqrestore(lock, flags);
(gdb)
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:172
172 if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED &&
(gdb)
173 !in_interrupt())
(gdb)
preempt_count () at arch/lkl/kernel/irq.c:173
173 !in_interrupt())
(gdb)
current_thread_info () at ./arch/lkl/include/asm/thread_info.h:46
46 return _current_thread_info;
(gdb)
preempt_count () at ./include/asm-generic/preempt.h:11
11 return READ_ONCE(current_thread_info()->preempt_count);
(gdb)
__read_once_size (size=<optimized out>, res=<optimized out>, p=<optimized out>) at ./include/linux/compiler.h:199
199 __READ_ONCE_SIZE;
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:172
172 if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED &&
(gdb)
171 {
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:174
174 run_irqs();
(gdb)
run_irqs () at arch/lkl/kernel/irq.c:129
129 for_each_bit(test_and_clear_irq_index_status(), check_irq_status, 0);
(gdb)
test_and_clear_irq_index_status () at arch/lkl/kernel/irq.c:128
128 {
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:175
175 irqs_enabled = flags;
(gdb)
176 }
(gdb)
atomic64_cmpxchg (v=0x7fe04009a6e0, o=0, n=1) at lib/atomic64.c:160
160 }
(gdb)
__down_write (sem=<optimized out>) at kernel/locking/rwsem.c:1363
1363 if (unlikely(!atomic_long_try_cmpxchg_acquire(&sem->count, &tmp,
(gdb)
1367 rwsem_set_owner(sem);
(gdb)
rwsem_set_owner (sem=<optimized out>) at kernel/locking/rwsem.c:1367
1367 rwsem_set_owner(sem);
(gdb)
atomic_long_set (i=<optimized out>, v=<optimized out>) at ./include/asm-generic/atomic-long.h:40
40 atomic64_set(v, i);
(gdb)
rwsem_set_owner (sem=<optimized out>) at kernel/locking/rwsem.c:176
176 atomic_long_set(&sem->owner, (long)current);
(gdb)
atomic_long_set (i=<optimized out>, v=<optimized out>) at ./include/asm-generic/atomic-long.h:40
40 atomic64_set(v, i);
(gdb)
atomic64_set (v=0x7fe04009a6e8, i=140601100807168) at lib/atomic64.c:63
63 raw_spin_lock_irqsave(lock, flags);
(gdb)
arch_local_irq_save () at ./include/asm-generic/irqflags.h:29
29 flags = arch_local_save_flags();
(gdb)
arch_local_save_flags () at arch/lkl/kernel/irq.c:166
166 {
(gdb)
167 return irqs_enabled;
(gdb)
166 {
(gdb)
168 }
(gdb)
arch_local_irq_save () at ./include/asm-generic/irqflags.h:30
30 arch_local_irq_restore(ARCH_IRQ_DISABLED);
(gdb)
29 flags = arch_local_save_flags();
(gdb)
30 arch_local_irq_restore(ARCH_IRQ_DISABLED);
(gdb)
arch_local_irq_restore (flags=0) at arch/lkl/kernel/irq.c:172
172 if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED &&
(gdb)
175 irqs_enabled = flags;
(gdb)
atomic64_set (v=0x7fe04009a6e8, i=140601100807168) at lib/atomic64.c:64
64 v->counter = i;
(gdb)
65 raw_spin_unlock_irqrestore(lock, flags);
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:172
172 if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED &&
(gdb)
173 !in_interrupt())
(gdb)
preempt_count () at arch/lkl/kernel/irq.c:173
173 !in_interrupt())
(gdb)
current_thread_info () at ./arch/lkl/include/asm/thread_info.h:46
46 return _current_thread_info;
(gdb)
preempt_count () at ./include/asm-generic/preempt.h:11
11 return READ_ONCE(current_thread_info()->preempt_count);
(gdb)
__read_once_size (size=<optimized out>, res=<optimized out>, p=<optimized out>) at ./include/linux/compiler.h:199
199 __READ_ONCE_SIZE;
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:172
172 if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED &&
(gdb)
171 {
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:174
174 run_irqs();
(gdb)
run_irqs () at arch/lkl/kernel/irq.c:129
129 for_each_bit(test_and_clear_irq_index_status(), check_irq_status, 0);
(gdb)
test_and_clear_irq_index_status () at arch/lkl/kernel/irq.c:128
128 {
(gdb)
arch_local_irq_restore (flags=1) at arch/lkl/kernel/irq.c:175
175 irqs_enabled = flags;
(gdb)
176 }
(gdb)
atomic64_set (v=0x7fe04009a6e8, i=140601100807168) at lib/atomic64.c:66
66 }
(gdb)
down_write (sem=0x7fe04009a6e0) at kernel/locking/rwsem.c:1502
1502 }
(gdb)
generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3486
3486 ret = generic_write_checks(iocb, from);
(gdb)
generic_write_checks (from=<optimized out>, iocb=<optimized out>) at mm/filemap.c:2991
2991 if (!iov_iter_count(from))
(gdb)
generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3486
3486 ret = generic_write_checks(iocb, from);
(gdb)
generic_write_checks (from=<optimized out>, iocb=<optimized out>) at mm/filemap.c:2995
2995 if (iocb->ki_flags & IOCB_APPEND)
(gdb)
2986 struct file *file = iocb->ki_filp;
(gdb)
2995 if (iocb->ki_flags & IOCB_APPEND)
(gdb)
2998 if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
(gdb)
generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3486
3486 ret = generic_write_checks(iocb, from);
(gdb)
generic_write_checks (from=<optimized out>, iocb=<optimized out>) at mm/filemap.c:3002
3002 ret = generic_write_check_limits(file, iocb->ki_pos, &count);
(gdb)
3001 count = iov_iter_count(from);
(gdb)
3002 ret = generic_write_check_limits(file, iocb->ki_pos, &count);
(gdb)
3001 count = iov_iter_count(from);
(gdb)
3002 ret = generic_write_check_limits(file, iocb->ki_pos, &count);
(gdb)
generic_write_check_limits (pos=0, count=0x7fe040b02b88, file=<optimized out>, file=<optimized out>) at mm/filemap.c:2955
2955 loff_t max_size = inode->i_sb->s_maxbytes;
(gdb)
2956 loff_t limit = rlimit(RLIMIT_FSIZE);
(gdb)
rlimit (limit=<optimized out>) at ./include/linux/sched/signal.h:706
706 return task_rlimit(current, limit);
(gdb)
task_rlimit (limit=<optimized out>, task=<optimized out>) at ./include/linux/sched/signal.h:695
695 return READ_ONCE(task->signal->rlim[limit].rlim_cur);
(gdb)
__read_once_size (size=<optimized out>, res=<optimized out>, p=<optimized out>) at ./include/linux/compiler.h:199
199 __READ_ONCE_SIZE;
(gdb)
generic_write_check_limits (pos=0, count=0x7fe040b02b88, file=<optimized out>, file=<optimized out>) at mm/filemap.c:2958
2958 if (limit != RLIM_INFINITY) {
(gdb)
2966 if (!(file->f_flags & O_LARGEFILE))
(gdb)
2967 max_size = MAX_NON_LFS;
(gdb)
2970 return -EFBIG;
(gdb)
2969 if (unlikely(pos >= max_size))
(gdb)
2972 *count = min(*count, max_size - pos);
(gdb)
2974 return 0;
(gdb)
2972 *count = min(*count, max_size - pos);
(gdb)
generic_write_checks (from=<optimized out>, iocb=<optimized out>) at mm/filemap.c:3003
3003 if (ret)
(gdb)
3004 return ret;
(gdb)
3003 if (ret)
(gdb)
3006 iov_iter_truncate(from, count);
(gdb)
iov_iter_truncate (count=<optimized out>, i=<optimized out>) at ./include/linux/uio.h:252
252 if (i->count > count)
(gdb)
generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3487
3487 if (ret > 0)
(gdb)
3488 ret = __generic_file_write_iter(iocb, from);
(gdb)
__generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3393
3393 struct file *file = iocb->ki_filp;
(gdb)
3401 current->backing_dev_info = inode_to_bdi(inode);
(gdb)
3394 struct address_space * mapping = file->f_mapping;
(gdb)
3401 current->backing_dev_info = inode_to_bdi(inode);
(gdb)
inode_to_bdi (inode=<optimized out>) at ./include/linux/backing-dev.h:160
160 return &noop_backing_dev_info;
(gdb)
__generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3395
3395 struct inode *inode = mapping->host;
(gdb)
3401 current->backing_dev_info = inode_to_bdi(inode);
(gdb)
inode_to_bdi (inode=<optimized out>) at ./include/linux/backing-dev.h:159
159 if (!inode)
(gdb)
162 sb = inode->i_sb;
(gdb)
164 if (sb_is_blkdev_sb(sb))
(gdb)
167 return sb->s_bdi;
(gdb)
__generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3401
3401 current->backing_dev_info = inode_to_bdi(inode);
(gdb)
3402 err = file_remove_privs(file);
(gdb)
file_remove_privs (file=0x7fe03e88be00) at fs/inode.c:1828
1828 struct dentry *dentry = file_dentry(file);
(gdb)
file_dentry (file=<optimized out>) at ./include/linux/fs.h:1305
1305 return d_real(file->f_path.dentry, file_inode(file));
(gdb)
file_inode (f=<optimized out>) at ./include/linux/fs.h:1300
1300 return f->f_inode;
(gdb)
file_dentry (file=<optimized out>) at ./include/linux/fs.h:1305
1305 return d_real(file->f_path.dentry, file_inode(file));
(gdb)
d_real (inode=<optimized out>, dentry=<optimized out>) at ./include/linux/dcache.h:575
575 if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
(gdb)
file_remove_privs (file=0x7fe03e88be00) at fs/inode.c:1839
1839 if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
(gdb)
1842 kill = dentry_needs_remove_privs(dentry);
(gdb)
dentry_needs_remove_privs (dentry=<optimized out>) at fs/inode.c:1798
1798 if (IS_NOSEC(inode))
(gdb)
dentry_needs_remove_privs (dentry=0x7fe040099900) at fs/inode.c:1792
1792 int dentry_needs_remove_privs(struct dentry *dentry)
(gdb)
1801 mask = should_remove_suid(dentry);
(gdb)
should_remove_suid (dentry=0x7fe040099900) at fs/inode.c:1766
1766 umode_t mode = d_inode(dentry)->i_mode;
(gdb)
1770 if (unlikely(mode & S_ISUID))
(gdb)
1777 if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
(gdb)
1783 return 0;
(gdb)
1784 }
(gdb)
dentry_needs_remove_privs (dentry=0x7fe040099900) at fs/inode.c:1802
1802 ret = security_inode_need_killpriv(dentry);
(gdb)
security_inode_need_killpriv (dentry=<optimized out>) at ./include/linux/security.h:781
781 return cap_inode_need_killpriv(dentry);
(gdb)
dentry_needs_remove_privs (dentry=0x7fe040099900) at fs/inode.c:1801
1801 mask = should_remove_suid(dentry);
(gdb)
1802 ret = security_inode_need_killpriv(dentry);
(gdb)
security_inode_need_killpriv (dentry=<optimized out>) at ./include/linux/security.h:781
781 return cap_inode_need_killpriv(dentry);
(gdb)
cap_inode_need_killpriv (dentry=0x7fe040099900) at security/commoncap.c:296
296 {
(gdb)
300 error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
(gdb)
296 {
(gdb)
300 error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
(gdb)
__vfs_getxattr (dentry=0x7fe040099900, inode=0x7fe04009a648, name=0x7fe0006bce98 "security.capability", value=0x0, size=0) at fs/xattr.c:306
306 handler = xattr_resolve_name(inode, &name);
(gdb)
303 {
(gdb)
306 handler = xattr_resolve_name(inode, &name);
(gdb)
303 {
(gdb)
306 handler = xattr_resolve_name(inode, &name);
(gdb)
xattr_resolve_name (inode=0x7fe04009a648, name=0x7fe040b02a38) at fs/xattr.c:59
59 if (!(inode->i_opflags & IOP_XATTR)) {
(gdb)
55 {
(gdb)
xattr_resolve_name (inode=0x7fe04009a648, name=0x7fe040b02a38) at fs/xattr.c:60
60 if (unlikely(is_bad_inode(inode)))
(gdb)
is_bad_inode (inode=0x7fe04009a648) at fs/bad_inode.c:226
226 return (inode->i_op == &bad_inode_ops);
(gdb)
225 {
(gdb)
is_bad_inode (inode=0x7fe04009a648) at fs/bad_inode.c:227
227 }
(gdb)
is_bad_inode (inode=0x7fe04009a648) at fs/bad_inode.c:226
226 return (inode->i_op == &bad_inode_ops);
(gdb)
227 }
(gdb)
xattr_resolve_name (inode=<optimized out>, name=<optimized out>) at fs/xattr.c:61
61 return ERR_PTR(-EIO);
(gdb)
60 if (unlikely(is_bad_inode(inode)))
(gdb)
62 return ERR_PTR(-EOPNOTSUPP);
(gdb)
79 }
(gdb)
__vfs_getxattr (dentry=0x7fe040099900, inode=0x7fe04009a648, name=0x7fe0006bce98 "security.capability", value=0x0, size=0) at fs/xattr.c:307
307 if (IS_ERR(handler))
(gdb)
312 }
(gdb)
cap_inode_need_killpriv (dentry=<optimized out>) at security/commoncap.c:301
301 return error > 0;
(gdb)
302 }
(gdb)
dentry_needs_remove_privs (dentry=0x7fe040099900) at fs/inode.c:1803
1803 if (ret < 0)
(gdb)
1806 mask |= ATTR_KILL_PRIV;
(gdb)
1808 }
(gdb)
file_remove_privs (file=0x7fe03eab2c00) at fs/inode.c:1843
1843 if (kill < 0)
(gdb)
1845 if (kill)
(gdb)
1848 inode_has_no_xattr(inode);
(gdb)
inode_has_no_xattr (inode=<optimized out>) at fs/inode.c:1848
1848 inode_has_no_xattr(inode);
(gdb)
is_sxid (mode=<optimized out>) at ./include/linux/fs.h:3462
3462 return (mode & S_ISUID) || ((mode & S_ISGID) && (mode & S_IXGRP));
(gdb)
inode_has_no_xattr (inode=<optimized out>) at ./include/linux/fs.h:3475
3475 if (!is_sxid(inode->i_mode) && (inode->i_sb->s_flags & SB_NOSEC))
(gdb)
file_remove_privs (file=0x7fe04009a648) at fs/inode.c:1848
1848 inode_has_no_xattr(inode);
(gdb)
inode_has_no_xattr (inode=<optimized out>) at ./include/linux/fs.h:3476
3476 inode->i_flags |= S_NOSEC;
(gdb)
file_remove_privs (file=0x7fe04009a648) at fs/inode.c:1851
1851 }
(gdb)
(gdb)
__generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02a38) at mm/filemap.c:3403
3403 if (err)
(gdb)
3406 err = file_update_time(file);
(gdb)
file_update_time (file=0x7fe03e88be00) at fs/inode.c:1869
1869 struct inode *inode = file_inode(file);
(gdb)
file_inode (f=<optimized out>) at ./include/linux/fs.h:1300
1300 return f->f_inode;
(gdb)
file_update_time (file=0x7fe03e88be00) at fs/inode.c:1875
1875 if (IS_NOCMTIME(inode))
(gdb)
1878 now = current_time(inode);
(gdb)
1880 sync_it = S_MTIME;
(gdb)
1878 now = current_time(inode);
(gdb)
current_time (inode=0x7fe04009a648) at fs/inode.c:2183
2183 ktime_get_coarse_real_ts64(&now);
(gdb)
2180 {
(gdb)
2183 ktime_get_coarse_real_ts64(&now);
(gdb)
ktime_get_coarse_real_ts64 (ts=0x7fe040b02aa0) at kernel/time/timekeeping.c:2166
2166 seq = read_seqcount_begin(&tk_core.seq);
(gdb)
read_seqcount_begin (s=<optimized out>) at kernel/time/timekeeping.c:2166
2166 seq = read_seqcount_begin(&tk_core.seq);
(gdb)
raw_read_seqcount_begin (s=<optimized out>) at kernel/time/timekeeping.c:2166
2166 seq = read_seqcount_begin(&tk_core.seq);
(gdb)
__read_seqcount_begin (s=<optimized out>) at kernel/time/timekeeping.c:2166
2166 seq = read_seqcount_begin(&tk_core.seq);
(gdb)
__read_once_size (size=<optimized out>, res=<optimized out>, p=<optimized out>) at ./include/linux/compiler.h:199
199 __READ_ONCE_SIZE;
(gdb)
(gdb)
__read_seqcount_begin (s=<optimized out>) at ./include/linux/seqlock.h:114
114 if (unlikely(ret & 1)) {
(gdb)
ktime_get_coarse_real_ts64 (ts=0x7fe040b02aa0) at kernel/time/timekeeping.c:2168
2168 *ts = tk_xtime(tk);
(gdb)
tk_xtime (tk=<optimized out>) at kernel/time/timekeeping.c:112
112 ts.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
(gdb)
ktime_get_coarse_real_ts64 (ts=0x7fe040b02aa0) at kernel/time/timekeeping.c:2168
2168 *ts = tk_xtime(tk);
(gdb)
2169 } while (read_seqcount_retry(&tk_core.seq, seq));
(gdb)
2170 }
(gdb)
current_time (inode=0x7fe04009a648) at fs/inode.c:2185
2185 if (unlikely(!inode->i_sb)) {
(gdb)
2190 return timespec64_trunc(now, inode->i_sb->s_time_gran);
(gdb)
timespec64_trunc (t=..., gran=1) at fs/inode.c:2154
2154 {
(gdb)
2156 if (gran == 1) {
(gdb)
2154 {
(gdb)
timespec64_trunc (t=..., gran=1) at fs/inode.c:2156
2156 if (gran == 1) {
(gdb)
2166 }
(gdb)
current_time (inode=0x7fe04009a648) at fs/inode.c:2191
2191 }
(gdb)
file_update_time (file=0x7fe03e88be00) at fs/inode.c:1879
1879 if (!timespec64_equal(&inode->i_mtime, &now))
(gdb)
timespec64_equal (b=<optimized out>, a=<optimized out>) at ./include/linux/time64.h:50
50 return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
(gdb)
(gdb)
file_update_time (file=0x7fe03e88be00) at fs/inode.c:1871
1871 int sync_it = 0;
(gdb)
1882 if (!timespec64_equal(&inode->i_ctime, &now))
(gdb)
timespec64_equal (b=<optimized out>, a=<optimized out>) at ./include/linux/time64.h:50
50 return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
(gdb)
1885 if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
(gdb)
1888 if (!sync_it)
(gdb)
1876 return 0;
(gdb)
1899 }
(gdb)
__generic_file_write_iter (iocb=0x7fe040b02bc0, from=0x7fe040b02c70) at mm/filemap.c:3407
3407 if (err)
(gdb)
3410 if (iocb->ki_flags & IOCB_DIRECT) {
(gdb)
3456 written = generic_perform_write(file, from, iocb->ki_pos);
(gdb)
generic_perform_write (file=0x7fe03e88be00, i=0x7fe040b02c70, pos=0) at mm/filemap.c:3289
3289 struct address_space *mapping = file->f_mapping;
(gdb)
3288 {
(gdb)
3292 ssize_t written = 0;
(gdb)
3290 const struct address_space_operations *a_ops = mapping->a_ops;
(gdb)
3327 status = a_ops->write_begin(file, mapping, pos, bytes, flags,
(gdb)
3290 const struct address_space_operations *a_ops = mapping->a_ops;
(gdb)
3327 status = a_ops->write_begin(file, mapping, pos, bytes, flags,
(gdb)
3302 offset = (pos & (PAGE_SIZE - 1));
(gdb)
3303 bytes = min_t(unsigned long, PAGE_SIZE - offset,
(gdb)
3302 offset = (pos & (PAGE_SIZE - 1));
(gdb)
3303 bytes = min_t(unsigned long, PAGE_SIZE - offset,
(gdb)
3317 if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
(gdb)
iov_iter_fault_in_readable (i=0x7fe040b02c70, bytes=4096) at lib/iov_iter.c:425
425 if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
(gdb)
419 {
(gdb)
iov_iter_fault_in_readable (i=0x7fe040b02c70, bytes=4096) at lib/iov_iter.c:426
426 iterate_iovec(i, bytes, v, iov, skip, ({
(gdb)
420 size_t skip = i->iov_offset;
(gdb)
419 {
(gdb)
426 iterate_iovec(i, bytes, v, iov, skip, ({
(gdb)
fault_in_pages_readable (size=<optimized out>, uaddr=<optimized out>) at ./include/linux/pagemap.h:573
573 const char __user *end = uaddr + size - 1;
(gdb)
575 if (unlikely(size == 0))
(gdb)
iov_iter_fault_in_readable (i=0x7fe040b02c70, bytes=4096) at lib/iov_iter.c:426
426 iterate_iovec(i, bytes, v, iov, skip, ({
(gdb)
fault_in_pages_readable (size=<optimized out>, uaddr=<optimized out>) at ./include/linux/pagemap.h:573
573 const char __user *end = uaddr + size - 1;
(gdb)
575 if (unlikely(size == 0))
(gdb)
578 if (unlikely(uaddr > end))
(gdb)
582 if (unlikely(__get_user(c, uaddr) != 0))
(gdb)
Thread 6 "ENCLAVE" received signal SIGSEGV, Segmentation fault.
fault_in_pages_readable (size=<optimized out>, uaddr=<optimized out>) at ./include/linux/pagemap.h:582
582 if (unlikely(__get_user(c, uaddr) != 0))
(gdb)
_host_signal_handler (sig_num=0, sig_info=0x0, sig_data=0x0) at /mnt/shaik/1108/sgx-lkl/openenclave/host/sgx/linux/exception.c:34
What is the invalid address? Is it inside the enclave? Until we are using LKL’s mmap, we have a very conservative response to access ok and will allow any access inside the enclave, even to kernel memory.
Okay, looking at the code, I understand this a bit better:
- The test allocates a page with
PROT_NONE
- The writev call is called with a pointer to this page.
- LKL tries to read from it and receives a trap.
This is precisely expected with the current code. The enclave_mmap implementation does not track page permissions (which causes some other issues as well) and so we can't usefully return failure in lkl_access_ok
.
I think this will Just Work(tm) once #597 is fixed, so I think this it is low priority to make it work with the existing enclave_mem code.
To add on, I think that fixing anything "largish" that isn't horribly broken in enclave_mmap would be time better spent on making #597 happen.