Bug 5042
Summary: | setrlimit/getrlimit broken on 32-bit platforms for limits > 2^32-1 | ||
---|---|---|---|
Product: | Memory Management | Reporter: | Michael Kerrisk (michael.kerrisk) |
Component: | Other | Assignee: | Alan (alan) |
Status: | RESOLVED OBSOLETE | ||
Severity: | normal | CC: | akpm, chrisw, drepper, jirislaby, mtk.manpages, narendramind |
Priority: | P2 | ||
Hardware: | i386 | ||
OS: | Linux | ||
Kernel Version: | 2.6.24 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
patch 2.6.24.3 rlimit64
fsizerlimit64.c patch-2.6.26-rlim64 fsizerlim64.c for patch-2.6.26-rlim64 working patch-2.6.26-rlim64 fsizerlim64.c: user space program to test working patch-2.6.26-rlim64 patch-2.6.29-rc2-rlim64 fsizerlim64.c: User space program to test the patch patch-2.6.29-rc2-rlim64 |
Description
Michael Kerrisk
2005-08-10 05:05:43 UTC
Michael, thanks for the comprehensive and clear report. I agree, the 32/64 syscall is the right way forward. The issue of what to do with 32bit version when value is > ulong has a fundamental ABI issue. If we add RLIM_SAVED_MAX and RLIM_SAVED_CUR, we have to reserve those (obvious choice would be 0xfffffffe), which wasn't reserved before, so there's still room for userspace confusion. Albeit, this is an unlikely used value, it is an ABI change. Also, how do we rationalize the difference between 32/64 bit RLIM_INFINITY? Hmm, I'll pick away at a patch to do this and see where it goes. It's certainly not pressing priority, so we don't need to worry for 2.6.13. * Michael Kerrisk (michael.kerrisk@gmx.net) wrote: > Thanks. I must confess to having a bit of help from Geoff > Clare of The Open Group in straightening out the details. Ah, nice ;-) > > I agree, the 32/64 syscall is the right way forward. > > The issue of what to do with 32bit version when value is > > ulong has a fundamental ABI issue. If we add RLIM_SAVED_MAX > > and RLIM_SAVED_CUR, we have to reserve those (obvious choice > > would be 0xfffffffe), which wasn't reserved before, so there's > > still room for userspace confusion. Albeit, this is an > > unlikely used value, it is an ABI change. > > Yes, I hadn't thought about that. In case it's of interest, > here are how RLIM_SAVED_CUR, RLIM_SAVED_MAX, and RLIM_INFINITY > seem to be defined (for 32-bits) on a few systems: Thanks. > RLIM_SAVED_CUR RLIM_SAVED_MAX RLIM_INFINITY > Irix 6.5 0x7ffffffd 0x7ffffffe 0x7fffffff > AIX 5.1 (RLIM_ININITY-2) (RLIM_ININITY-1) 0x7FFFFFFF > Solaris 8 0x7ffffffd 0x7ffffffe 0x7fffffff Yeah, I figured we'd just overlap RLIM_SAVED_CUR and RLIM_SAVED_MAX. Since they have the same meaning for different fields in a struct. I suppose if someone wanted to lower their hard limit to the soft limit it would be useful to be able to distinguish. I had just hoped to rob as few currently legal values as possible. (Of course, not to mention that we have RLIM_INFINITY as 0xffffffff and 0x7fffffff depending on hardware platform, but that's not a real issue). > http://bugzilla.kernel.org/show_bug.cgi?id=5042 > > > I agree, the 32/64 syscall is the right way forward. > > > The issue of what to do with 32bit version when value is > > > ulong has a fundamental ABI issue. If we add RLIM_SAVED_MAX > > > and RLIM_SAVED_CUR, we have to reserve those (obvious choice > > > would be 0xfffffffe), which wasn't reserved before, so there's > > > still room for userspace confusion. Albeit, this is an > > > unlikely used value, it is an ABI change. > > > > Yes, I hadn't thought about that. In case it's of interest, > > here are how RLIM_SAVED_CUR, RLIM_SAVED_MAX, and RLIM_INFINITY > > seem to be defined (for 32-bits) on a few systems: > > Thanks. > > > RLIM_SAVED_CUR RLIM_SAVED_MAX RLIM_INFINITY > > Irix 6.5 0x7ffffffd 0x7ffffffe 0x7fffffff > > AIX 5.1 (RLIM_ININITY-2) (RLIM_ININITY-1) 0x7FFFFFFF > > Solaris 8 0x7ffffffd 0x7ffffffe 0x7fffffff > > Yeah, I figured we'd just overlap RLIM_SAVED_CUR and RLIM_SAVED_MAX. > Since they have the same meaning for different fields in a struct. > I suppose if someone wanted to lower their hard limit to the soft limit it > would be useful to be able to distinguish. Yes. If (and SUSv3 says only if) either of these two constant values is returned for a particular resource limit by getrlimit(), then they can also be used in a subsequent setrlimit() call to change the settings of that limit: if either rlim_cur or rlim_max is set to RLIM_SAVED_CUR, then the resource limit is set to the soft limit value that was in effect before the call; if either rlim_cur or rlim_max is set to RLIM_SAVED_MAX, then the resource limit is set to the hard limit value that was in effect before the call. So, I think the two values must be distinct. Cheers, Michael This is a bit ugly. I suppose we could fix it by adding a new rlimit which specifies RLIMIT_FSIZE in units of getpagesize(). Or add a new syscall just to set RLIMIT_FSIZE. All rather unpleasant. Ulrich, any thoughts? It doesn't seem terribly important? glibc is waiting for the longest time for a [gs]etrlimit64 implementation in the kernel. The LFS extensions define such interfaces and we implement them. But obviously it is done using the old 32-bit interfaces and therefore this limit. struct rlimit64 is simply a type with 64-bit members, otherwise it's the same as struct rlimit. I suggest implementing these syscalls. Of course we could also say "who cares about 32-bit these days" and continue to ignore the problem. I have implemented the two syscalls and herewith I am attaching the patch for 2.6.24.3 and a test program (fsizerlim64.c) to get the limits. Issues Facing: * Though the limits are initialized to RLIM64_INFINITY, garbage values are set to them. -The outof the test program is: narendra@infinity:~$ gcc fsizerlim64.c narendra@infinity:~$ ./a.out retval : 0 rlim | max64 = f496719400000001 | cur64 = f4967194 narendra@infinity:~$ ./a.out retval : 0 rlim | max64 = fe86a13df498a628 | cur64 = f499ff98f499ff98 -Placed some printks in sys_getrlimit64, the output of dmesg is as follows: dmesg [ 111.221402] resource = 1, RLIM64_INFINITY = ffffffffffffffff, RLIMIT_FSIZE = 1, RLIM64_NLIMITS = 2 [ 111.221411] current rlim64 : max64 = f4967194, cur64 = f496719400000001 [ 111.221416] value (local var, before) : max64 = c02f9730b7f4cce0, cur64 = b7f18ff4f4ae5e00 [ 111.221421] value (after assignment) : max64 = f4967194, cur64 = f496719400000001 [ 118.437395] resource = 1, RLIM64_INFINITY = ffffffffffffffff, RLIMIT_FSIZE = 1, RLIM64_NLIMITS = 2 [ 118.437406] current rlim64 : max64 = f499ff98f499ff98, cur64 = fe86a13df498a628 [ 118.437411] value (local var, before) : max64 = c02f9730b7f94ce0, cur64 = b7f60ff4f4b41e00 [ 118.437419] value (after assignment) : max64 = f499ff98f499ff98, cur64 = fe86a13df498a628 Created attachment 15346 [details]
patch 2.6.24.3 rlimit64
Created attachment 15347 [details]
fsizerlimit64.c
Can anybody provide indication to proceed further. Please send the patch to linux-kernel@vger.kernel.org linux-fsdevel@vger.kernel.org and myself as per Documentation/SubmittingPatches, http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt, etc. Thanks. Hi Andrew, As per documentation, submitted the patch to the above mailing lists on 23rd & 31st of Mar-2008. May I know when it can be merged to main-line of kernel tree. Thanks. I looked over the patch briefly and I had rather a lot of issues with it. It will take me some time to comment on them in detail. I'll try to get onto that. Feel free to remind me if I don't. (In reply to comment #12) > I looked over the patch briefly and I had rather a lot of issues with it. > It will take me some time to comment on them in detail. I'll try to get > onto that. Feel free to remind me if I don't. Hi Andrew, This is your reminder ;-). Narendra, if you do another iteration of this patch, please CC me when writing to the lists. Cheers, Michael I've again created a patch for kernel v2.6.26 and tested it but running into the issues mentioned in Comment #6. I would appriciate if any body help me out to resolve the issue. Herewith I am attaching the patch and the program whereby we can retrieve the limit values stored in the kernel. Overview of the Patch ===================== The patch addes two syscalls such as sys_getrlimit64() sys_setrlimit64() 1. Header Files include/linux/resource.h Defined 'struct rlimit64' to accommodate limit max bounderies include/linux/sched.h Declared struct rlimit64 rlim64[RLIM64_NLIMITS]; in task_struct to have the limits for each process include/linux/init_task.h Initialized .rlim64 with INIT_RLIMITS64 ( is defined in include/asm-generic/resource.h) include/asm-x86/unistd_32.h Defined syscall numbers for sys_setrlimit64(327), sys_getrlimit64(328) 2. Source Files (.c) kernel/sys.c added sys_getrlimit64, sys_setrlimit64 functions. Created attachment 17025 [details]
patch-2.6.26-rlim64
patch-2.6.26-rlim64
Created attachment 17026 [details]
fsizerlim64.c for patch-2.6.26-rlim64
fsizerlim64.c for patch-2.6.26-rlim64
(In reply to comment #14) > I've again created a patch for kernel v2.6.26 and tested it but running into > the issues mentioned in Comment #6. Issue with patch is that when process being created, 'rlim64' object (of signal object in task_struct) is also to be assigned appropriate values inaddition to 'rlim' This is done by modifying kernel/fork.c and kernel/exit.c > > I would appriciate if any body help me out to resolve the issue. > > Herewith I am attaching the patch and the program whereby we can retrieve the > limit values stored in the kernel. > > Overview of the Patch > ===================== > The patch addes two syscalls such as sys_getrlimit64() sys_setrlimit64() > 1. Header Files > include/linux/resource.h > Defined 'struct rlimit64' to accommodate limit max bounderies > include/linux/sched.h > Declared struct rlimit64 rlim64[RLIM64_NLIMITS]; in task_struct to have > the limits for each process > include/linux/init_task.h > Initialized .rlim64 with INIT_RLIMITS64 > ( is defined in include/asm-generic/resource.h) > include/asm-x86/unistd_32.h > Defined syscall numbers for sys_setrlimit64(327), sys_getrlimit64(328) > 2. Source Files (.c) > kernel/sys.c > added sys_getrlimit64, sys_setrlimit64 functions. > Now that the modified patch is working as expected and the test results are observed as follows when I ran fsizerlim64.c: getrlimit64: Limits in the Kernel .... retval : 0 rlim | max64 = ffffffffffffffff rlim | cur64 = ffffffffffffffff setrlimit64: setting the following limits ... retval : 0 rlim | max64 = 1122334455667788 rlim | cur64 = 1122334455667788 getrlimit64: Limits in the Kernel set .... retval : 0 rlim | max64 = 1122334455667788 rlim | cur64 = 1122334455667788 The patch and the user space program can be found in the attachment. Created attachment 17145 [details]
working patch-2.6.26-rlim64
working patch-2.6.26-rlim64
Created attachment 17146 [details]
fsizerlim64.c: user space program to test working patch-2.6.26-rlim64
fsizerlim64.c: user space program to test working patch-2.6.26-rlim64
Hi Andrew, As per documentation, submitted the patch to the mailing lists on 08-08-2008 & 19-Aug-2008. May I know when it can be merged to main-line of kernel tree. Thanks, Narendra. Grabbing this bug to progress it Hi Andrew, Attaching the patch, patch-2.6.29-rc2-rlim64, for latest pre-patched kernel, linux-2.6.29-rc2. Can you consider this patch for merging. Thanks, Narendra. Created attachment 19861 [details]
patch-2.6.29-rc2-rlim64
patch-2.6.29-rc2-rlim64
Created attachment 19862 [details]
fsizerlim64.c: User space program to test the patch patch-2.6.29-rc2-rlim64
fsizerlim64.c: User space program to test the patch patch-2.6.29-rc2-rlim64
Hi Folks, I have sent patch to linux-kernel and linux-fsdel but the patch is not available in the mailing lists archives. Can anybody help me in sending the patch to the above mailing lists and also let me know what could be the problem. Note that my mail-id has been subscribed to the lists. Thanks in advance. Thanks, Narendr. Any progress here? What is the patch supposed to do? It only stores the rlimit64 without any use of it except returning values from that back via getrlimit64. The rest of resource handling in the kernel still uses 32-bit rlimits. (In reply to comment #26) > Any progress here? > > What is the patch supposed to do? It only stores the rlimit64 without any use > of it except returning values from that back via getrlimit64. The rest of > resource handling in the kernel still uses 32-bit rlimits. Started working on this as at last I've got x84_64 platform. Here are the tasks involved to completed the task: 1. Insert a check to send a signal SIGXFSZ if user exceeds file limit rlim64_cur. --> DONE 2. Add compat system calls for setrlimit64/getrlimit64. --> IN PROGRESS The 2.6.36 kernel adds prlimit(), which does not suffer the problem noted in this bug. The new system call could be used to fix this problem within the glibc wrappers. I've reported this against glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=12201 Just for the record on why this bug was (rightly) marked obsolete. As a consequence of http://sources.redhat.com/bugzilla/show_bug.cgi?id=12201, glibc's getrlimit/setrlimit wrappers have been modified to use prlimit(2), which does not suffer this issue. |