* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 @ 2016-08-16 11:55 Cyril Hrubis 2016-08-16 14:34 ` Cyril Hrubis 2016-08-16 20:04 ` Michael Kerrisk 0 siblings, 2 replies; 14+ messages in thread From: Cyril Hrubis @ 2016-08-16 11:55 UTC (permalink / raw) To: ltp If we pass struct flock to the F_OFD_XXX fcntl() it will fail with EINVAL with a 32bit binary. That is because glibc uses fcntl64() by default but the struct flock uses 32bit off_t for 32bit binaries (unless _FILE_OFFSET_BITS=64) and kernel always expect flock64 for F_OFD_XXX in fcntl64(). Hence kernel will read some garbage that is a few bytes after the 32bit flock structure in this case which will likely end up with the syscall returning EINVAL. Signed-off-by: Cyril Hrubis <chrubis@suse.cz> CC: Yuriy Kolerov <Yuriy.Kolerov@synopsys.com> --- man2/fcntl.2 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man2/fcntl.2 b/man2/fcntl.2 index f0c1acf..4606709 100644 --- a/man2/fcntl.2 +++ b/man2/fcntl.2 @@ -533,7 +533,7 @@ As with traditional advisory locks, the third argument to .BR fcntl (), .IR lock , is a pointer to an -.IR flock +.IR flock64 structure. By contrast with traditional record locks, the .I l_pid @@ -543,7 +543,7 @@ when using the commands described below. The commands for working with open file description locks are analogous to those used with traditional locks: .TP -.BR F_OFD_SETLK " (\fIstruct flock *\fP)" +.BR F_OFD_SETLK " (\fIstruct flock64 *\fP)" Acquire an open file description lock (when .I l_type is @@ -564,7 +564,7 @@ this call returns \-1 and sets to .BR EAGAIN . .TP -.BR F_OFD_SETLKW " (\fIstruct flock *\fP)" +.BR F_OFD_SETLKW " (\fIstruct flock64 *\fP)" As for .BR F_OFD_SETLK , but if a conflicting lock is held on the file, then wait for that lock to be @@ -578,7 +578,7 @@ set to see .BR signal (7)). .TP -.BR F_OFD_GETLK " (\fIstruct flock *\fP)" +.BR F_OFD_GETLK " (\fIstruct flock64 *\fP)" On input to this call, .I lock describes an open file description lock we would like to place on the file. -- 2.7.3 -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-16 11:55 [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 Cyril Hrubis @ 2016-08-16 14:34 ` Cyril Hrubis 2016-08-16 20:04 ` Michael Kerrisk 1 sibling, 0 replies; 14+ messages in thread From: Cyril Hrubis @ 2016-08-16 14:34 UTC (permalink / raw) To: ltp Hi! > If we pass struct flock to the F_OFD_XXX fcntl() it will fail with > EINVAL with a 32bit binary. That is because glibc uses fcntl64() by > default but the struct flock uses 32bit off_t for 32bit binaries (unless > _FILE_OFFSET_BITS=64) and kernel always expect flock64 for F_OFD_XXX in > fcntl64(). Hence kernel will read some garbage that is a few bytes after > the 32bit flock structure in this case which will likely end up with the > syscall returning EINVAL. Here is also a commit that fixes the corresponding LTP testcase: https://github.com/linux-test-project/ltp/commit/ae09800dfed8630f67796501bef3a88bb4fd3daa Before this the fcntl34 test was failing on 32bit platform or with CFLAGS=-m32 LDFLAGS=-m32 passed to configure. Before: testcases/kernel/syscalls/fcntl $./fcntl34 tst_test.c:756: INFO: Timeout per run is 0h 05m 00s fcntl34.c:104: INFO: write to a file inside threads with OFD locks fcntl34.c:48: INFO: spawning '12' threads fcntl34.c:79: BROK: fcntl() failed: EINVAL Summary: passed 0 failed 0 skipped 0 warnings 0 After: testcases/kernel/syscalls/fcntl $./fcntl34 tst_test.c:756: INFO: Timeout per run is 0h 05m 00s fcntl34.c:104: INFO: write to a file inside threads with OFD locks fcntl34.c:48: INFO: spawning '12' threads fcntl34.c:57: INFO: waiting for '12' threads fcntl34.c:113: INFO: verifying file's data fcntl34.c:141: PASS: OFD locks synchronized access between threads Summary: passed 1 failed 0 skipped 0 warnings 0 -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-16 11:55 [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 Cyril Hrubis 2016-08-16 14:34 ` Cyril Hrubis @ 2016-08-16 20:04 ` Michael Kerrisk 2016-08-16 23:41 ` Jeff Layton 2016-08-17 7:44 ` Cyril Hrubis 1 sibling, 2 replies; 14+ messages in thread From: Michael Kerrisk @ 2016-08-16 20:04 UTC (permalink / raw) To: ltp [Jeff, can you comment?] Hi Cyril, On 08/16/2016 11:55 PM, Cyril Hrubis wrote: > If we pass struct flock to the F_OFD_XXX fcntl() it will fail with > EINVAL with a 32bit binary. That is because glibc uses fcntl64() by > default but the struct flock uses 32bit off_t for 32bit binaries (unless > _FILE_OFFSET_BITS=64) and kernel always expect flock64 for F_OFD_XXX in > fcntl64(). Hence kernel will read some garbage that is a few bytes after > the 32bit flock structure in this case which will likely end up with the > syscall returning EINVAL. Okay -- I confirm the problem you report. I'm just not sure that the patch below is the best fix. So, to summarize: * On 64-bit, flock{} and flock64{} are the same structure. * On 32-bit, flock{} and flock64{} are different. * On 32-bit, F_OFD operations require flock64{}, but the traditional F_* lock operations do not. * To use flock64{} with F_OFD operations, we can either explicitly use flock64{} or we can compile with -D_FILE_OFFSET_BITS=64 One solution would be your patch below, but it feels wrong: on 64-bit flock{} suffices, and is consistent with the traditional F_* operations. An alternative would be a note in the man page that says something along the lines that on 32-bit, one must compile with -D_FILE_OFFSET_BITS=64 when using the F_OFD operations. Your thoughts? Cheers, Michael > Signed-off-by: Cyril Hrubis <chrubis@suse.cz> > CC: Yuriy Kolerov <Yuriy.Kolerov@synopsys.com> > --- > man2/fcntl.2 | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/man2/fcntl.2 b/man2/fcntl.2 > index f0c1acf..4606709 100644 > --- a/man2/fcntl.2 > +++ b/man2/fcntl.2 > @@ -533,7 +533,7 @@ As with traditional advisory locks, the third argument to > .BR fcntl (), > .IR lock , > is a pointer to an > -.IR flock > +.IR flock64 > structure. > By contrast with traditional record locks, the > .I l_pid > @@ -543,7 +543,7 @@ when using the commands described below. > The commands for working with open file description locks are analogous > to those used with traditional locks: > .TP > -.BR F_OFD_SETLK " (\fIstruct flock *\fP)" > +.BR F_OFD_SETLK " (\fIstruct flock64 *\fP)" > Acquire an open file description lock (when > .I l_type > is > @@ -564,7 +564,7 @@ this call returns \-1 and sets > to > .BR EAGAIN . > .TP > -.BR F_OFD_SETLKW " (\fIstruct flock *\fP)" > +.BR F_OFD_SETLKW " (\fIstruct flock64 *\fP)" > As for > .BR F_OFD_SETLK , > but if a conflicting lock is held on the file, then wait for that lock to be > @@ -578,7 +578,7 @@ set to > see > .BR signal (7)). > .TP > -.BR F_OFD_GETLK " (\fIstruct flock *\fP)" > +.BR F_OFD_GETLK " (\fIstruct flock64 *\fP)" > On input to this call, > .I lock > describes an open file description lock we would like to place on the file. > -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-16 20:04 ` Michael Kerrisk @ 2016-08-16 23:41 ` Jeff Layton 2016-08-17 1:08 ` Michael Kerrisk 2016-08-17 8:10 ` Cyril Hrubis 2016-08-17 7:44 ` Cyril Hrubis 1 sibling, 2 replies; 14+ messages in thread From: Jeff Layton @ 2016-08-16 23:41 UTC (permalink / raw) To: ltp On Wed, 2016-08-17 at 08:04 +1200, Michael Kerrisk (man-pages) wrote: > [Jeff, can you comment?] > > Hi Cyril, > > On 08/16/2016 11:55 PM, Cyril Hrubis wrote: > > > > If we pass struct flock to the F_OFD_XXX fcntl() it will fail with > > EINVAL with a 32bit binary. That is because glibc uses fcntl64() by > > default but the struct flock uses 32bit off_t for 32bit binaries (unless > > _FILE_OFFSET_BITS=64) and kernel always expect flock64 for F_OFD_XXX in > > fcntl64(). Hence kernel will read some garbage that is a few bytes after > > the 32bit flock structure in this case which will likely end up with the > > syscall returning EINVAL. > > Okay -- I confirm the problem you report. I'm just not sure that the > patch below is the best fix. So, to summarize: > > * On 64-bit, flock{} and flock64{} are the same structure. > * On 32-bit, flock{} and flock64{} are different. > * On 32-bit, F_OFD operations require flock64{}, but the traditional > F_* lock operations do not. > * To use flock64{} with F_OFD operations, we can either explicitly use > flock64{} or we can compile with -D_FILE_OFFSET_BITS=64 > > One solution would be your patch below, but it feels wrong: on 64-bit > flock{} suffices, and is consistent with the traditional F_* operations. > An alternative would be a note in the man page that says something along > the lines that on 32-bit, one must compile with -D_FILE_OFFSET_BITS=64 > when using the F_OFD operations. > > Your thoughts? > > Cheers, > > Michael > This sounds like a regular old bug, rather than a documentation issue. The way the kernel works is that if you call fcntl(), then you need to pass in a struct flock. If you call fcntl64() then you need to pass in a struct flock64. Of course this is only on 32-bit arches. On 64-bit, it's there is no flock64 or fcntl64. Typically, glibc papers over all of this by deciding which syscall it's going to use based on -D_FILE_OFFSET_BITS. IIRC, it basically redefines the fields in struct flock to be like the one in struct flock64, so you shouldn't need to do anything special here. It sounds here like you got a mismatch, somehow and were calling fcntl64() with the smaller struct flock? Or was it vice versa? What would be ideal would be a small reproducer program, and instructions on how to build it. With that we should be able to nail down why this is happening. Also, what arch are you using here? > > > > Signed-off-by: Cyril Hrubis <chrubis@suse.cz> > > > > CC: Yuriy Kolerov <Yuriy.Kolerov@synopsys.com> > > --- > > man2/fcntl.2 | 8 ++++---- > > 1 file changed, 4 insertions(+), 4 deletions(-) > > > > diff --git a/man2/fcntl.2 b/man2/fcntl.2 > > index f0c1acf..4606709 100644 > > --- a/man2/fcntl.2 > > +++ b/man2/fcntl.2 > > @@ -533,7 +533,7 @@ As with traditional advisory locks, the third argument to > > .BR fcntl (), > > .IR lock , > > is a pointer to an > > -.IR flock > > +.IR flock64 > > structure. > > By contrast with traditional record locks, the > > .I l_pid > > @@ -543,7 +543,7 @@ when using the commands described below. > > The commands for working with open file description locks are analogous > > to those used with traditional locks: > > .TP > > -.BR F_OFD_SETLK " (\fIstruct flock *\fP)" > > +.BR F_OFD_SETLK " (\fIstruct flock64 *\fP)" > > Acquire an open file description lock (when > > .I l_type > > is > > @@ -564,7 +564,7 @@ this call returns \-1 and sets > > to > > .BR EAGAIN . > > .TP > > -.BR F_OFD_SETLKW " (\fIstruct flock *\fP)" > > +.BR F_OFD_SETLKW " (\fIstruct flock64 *\fP)" > > As for > > .BR F_OFD_SETLK , > > but if a conflicting lock is held on the file, then wait for that lock to be > > @@ -578,7 +578,7 @@ set to > > see > > .BR signal (7)). > > .TP > > -.BR F_OFD_GETLK " (\fIstruct flock *\fP)" > > +.BR F_OFD_GETLK " (\fIstruct flock64 *\fP)" > > On input to this call, > > .I lock > > describes an open file description lock we would like to place on the file. > > > > -- Jeff Layton <jlayton@poochiereds.net> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-16 23:41 ` Jeff Layton @ 2016-08-17 1:08 ` Michael Kerrisk 2016-08-17 8:10 ` Cyril Hrubis 1 sibling, 0 replies; 14+ messages in thread From: Michael Kerrisk @ 2016-08-17 1:08 UTC (permalink / raw) To: ltp Hi Jeff, Thanks for jumping in. On 17 August 2016 at 11:41, Jeff Layton <jlayton@poochiereds.net> wrote: > On Wed, 2016-08-17 at 08:04 +1200, Michael Kerrisk (man-pages) wrote: >> [Jeff, can you comment?] >> >> Hi Cyril, >> >> On 08/16/2016 11:55 PM, Cyril Hrubis wrote: >> > >> > If we pass struct flock to the F_OFD_XXX fcntl() it will fail with >> > EINVAL with a 32bit binary. That is because glibc uses fcntl64() by >> > default but the struct flock uses 32bit off_t for 32bit binaries (unless >> > _FILE_OFFSET_BITS=64) and kernel always expect flock64 for F_OFD_XXX in >> > fcntl64(). Hence kernel will read some garbage that is a few bytes after >> > the 32bit flock structure in this case which will likely end up with the >> > syscall returning EINVAL. >> >> Okay -- I confirm the problem you report. I'm just not sure that the >> patch below is the best fix. So, to summarize: >> >> * On 64-bit, flock{} and flock64{} are the same structure. >> * On 32-bit, flock{} and flock64{} are different. >> * On 32-bit, F_OFD operations require flock64{}, but the traditional >> F_* lock operations do not. >> * To use flock64{} with F_OFD operations, we can either explicitly use >> flock64{} or we can compile with -D_FILE_OFFSET_BITS=64 >> >> One solution would be your patch below, but it feels wrong: on 64-bit >> flock{} suffices, and is consistent with the traditional F_* operations. >> An alternative would be a note in the man page that says something along >> the lines that on 32-bit, one must compile with -D_FILE_OFFSET_BITS=64 >> when using the F_OFD operations. >> >> Your thoughts? >> >> Cheers, >> >> Michael >> > > This sounds like a regular old bug, rather than a documentation issue. > > The way the kernel works is that if you call fcntl(), then you need to > pass in a struct flock. If you call fcntl64() then you need to pass in > a struct flock64. Of course this is only on 32-bit arches. On 64-bit, > it's there is no flock64 or fcntl64. > > Typically, glibc papers over all of this by deciding which syscall it's > going to use based on -D_FILE_OFFSET_BITS. IIRC, it basically redefines > the fields in struct flock to be like the one in struct flock64, so you > shouldn't need to do anything special here. > > It sounds here like you got a mismatch, somehow and were calling > fcntl64() with the smaller struct flock? Or was it vice versa? > > What would be ideal would be a small reproducer program, and > instructions on how to build it. With that we should be able to nail > down why this is happening. > > Also, what arch are you using here? x86 is enough. 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x--- #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #ifndef F_OFD_GETLK /* In case we are on a system with glibc version earlier than 2.20 */ #define F_OFD_GETLK 36 #define F_OFD_SETLK 37 #define F_OFD_SETLKW 38 #endif #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) #define usageErr(msg, progName) \ do { fprintf(stderr, "Usage: "); \ fprintf(stderr, msg, progName); \ exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { int fd; struct flock fl; if (argc < 2) usageErr("%s file\n", argv[0]); fd = open(argv[1], O_CREAT | O_RDWR, 0600); if (fd == -1) errExit("open"); memset(&fl, 99, sizeof(fl)); /* Ensure any uninitialized bytes contain junk */ fl.l_start = 0; fl.l_len = 1; fl.l_type = F_WRLCK; fl.l_whence = SEEK_CUR; fl.l_pid = 0; if (fcntl(fd, F_OFD_SETLK, &fl) == -1) errExit("fcntl"); } 8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x---8x--- $ cc -m32 prog.c $ ./a.out /tmp/x fcntl: Invalid argument Cheers, Michael ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-16 23:41 ` Jeff Layton 2016-08-17 1:08 ` Michael Kerrisk @ 2016-08-17 8:10 ` Cyril Hrubis 2016-08-17 11:44 ` Jeff Layton 1 sibling, 1 reply; 14+ messages in thread From: Cyril Hrubis @ 2016-08-17 8:10 UTC (permalink / raw) To: ltp Hi! > The way the kernel works is that if you call fcntl(), then you need to > pass in a struct flock. If you call fcntl64() then you need to pass in > a struct flock64. Of course this is only on 32-bit arches. On 64-bit, > it's there is no flock64 or fcntl64. This does not seem to be the case. It looks like kernel expect F_{SET,GET}LK to be 32bit for fcntl64() as well. It just calls do_fcntl() that casts the pointer to struct flock that seems to be defined with __kernel_off_t in the uapi headers which is alias to long. And the same in the compat implementation, there the F_{SET,GET}LK works with struct compat_flock that has 32bit off_t as well. Then we have the F_{SET,GET}LK64 that expect 64bit flock and the F_OFD_XXX behaves exactly same. As a matter of the fact they are handled mostly in the same branches of the switch() statements which lead me to belive that they were intended to be used with flock64 explicitly. Glibc does not seem to do much work here. The only thing it does is to switch between the F_{SET,GET}LK and F_{SET,GET}LK64 based on _FILE_OFFSET_BITS to match the off_t type in the flock structure. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 8:10 ` Cyril Hrubis @ 2016-08-17 11:44 ` Jeff Layton 2016-08-17 11:53 ` Cyril Hrubis 2016-08-17 19:44 ` Michael Kerrisk 0 siblings, 2 replies; 14+ messages in thread From: Jeff Layton @ 2016-08-17 11:44 UTC (permalink / raw) To: ltp On Wed, 2016-08-17 at 10:10 +0200, Cyril Hrubis wrote: > Hi! > > > > The way the kernel works is that if you call fcntl(), then you need to > > pass in a struct flock. If you call fcntl64() then you need to pass in > > a struct flock64. Of course this is only on 32-bit arches. On 64-bit, > > it's there is no flock64 or fcntl64. > > This does not seem to be the case. > > It looks like kernel expect F_{SET,GET}LK to be 32bit for fcntl64() as > well. It just calls do_fcntl() that casts the pointer to struct flock > that seems to be defined with __kernel_off_t in the uapi headers which > is alias to long. > > And the same in the compat implementation, there the F_{SET,GET}LK works > with struct compat_flock that has 32bit off_t as well. > > Then we have the F_{SET,GET}LK64 that expect 64bit flock and the > F_OFD_XXX behaves exactly same. As a matter of the fact they are handled > mostly in the same branches of the switch() statements which lead me to > belive that they were intended to be used with flock64 explicitly. > > Glibc does not seem to do much work here. The only thing it does is to > switch between the F_{SET,GET}LK and F_{SET,GET}LK64 based on > _FILE_OFFSET_BITS to match the off_t type in the flock structure. > Thanks, I think I understand now. I think there are a couple of potential fixes... The simplest thing is to do what you're suggesting and simply document that F_OFD_* locks require large file offsets. If we do that though, then I think we also ought to do something to ensure that the build breaks if you try to use F_OFD_* commands without large offsets. The simplest way would be to put the F_OFD_* constant definitions under "#ifdef __USE_FILE_OFFSET64", but I'm open to suggestions that would make the compiler error out with a more helpful error message. The other option would be to fix glibc and the kernel to handle legacy struct flock with F_OFD_ cmd values. That would mean adding F_OFD_*64 command values and fixing glibc to swap them in appropriately. That's doable, but I'm not sure it's really worth it. We'd also have to think about how to handle the old kernel/new glibc case (and vice versa), and that probably won't be trivial. I'm leaning toward option #1 here. I can cook up a patch for glibc if you guys agree. Thoughts? -- Jeff Layton <jlayton@poochiereds.net> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 11:44 ` Jeff Layton @ 2016-08-17 11:53 ` Cyril Hrubis 2016-08-17 13:14 ` Jeff Layton 2016-08-17 19:44 ` Michael Kerrisk 1 sibling, 1 reply; 14+ messages in thread From: Cyril Hrubis @ 2016-08-17 11:53 UTC (permalink / raw) To: ltp Hi! > Thanks, I think I understand now. I think there are a couple of > potential fixes... > > The simplest thing is to do what you're suggesting and simply document > that F_OFD_* locks require large file offsets. If we do that though, > then I think we also ought to do something to ensure that the build > breaks if you try to use F_OFD_* commands without large offsets. > > The simplest way would be to put the F_OFD_* constant definitions under > "#ifdef??__USE_FILE_OFFSET64", but I'm open to suggestions that would > make the compiler error out with a more helpful error message. Hmm, I do not think that this is a good idea. The usuall way how to handle missing constants are fallback definitions such as: #ifndef F_OFD_FOO # define F_OFD_FOO xyz #endif This wouldn't do much. Also these should be only disable on 32bit if __USE_FILE_OFFSET64 is not defined. But you likely meant that here. > The other option would be to fix glibc and the kernel to handle legacy > struct flock with F_OFD_ cmd values. That would mean adding F_OFD_*64 > command values and fixing glibc to swap them in appropriately. That's > doable, but I'm not sure it's really worth it. We'd also have to think > about how to handle the old kernel/new glibc case (and vice versa), and > that probably won't be trivial. I do not think that this is worth the work either. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 11:53 ` Cyril Hrubis @ 2016-08-17 13:14 ` Jeff Layton 2016-08-17 13:19 ` Cyril Hrubis 0 siblings, 1 reply; 14+ messages in thread From: Jeff Layton @ 2016-08-17 13:14 UTC (permalink / raw) To: ltp On Wed, 2016-08-17 at 13:53 +0200, Cyril Hrubis wrote: > Hi! > > > > Thanks, I think I understand now. I think there are a couple of > > potential fixes... > > > > The simplest thing is to do what you're suggesting and simply > > document > > that F_OFD_* locks require large file offsets. If we do that > > though, > > then I think we also ought to do something to ensure that the build > > breaks if you try to use F_OFD_* commands without large offsets. > > > > The simplest way would be to put the F_OFD_* constant definitions > > under > > "#ifdef??__USE_FILE_OFFSET64", but I'm open to suggestions that > > would > > make the compiler error out with a more helpful error message. > > Hmm, I do not think that this is a good idea. The usuall way how to > handle missing constants are fallback definitions such as: > > #ifndef F_OFD_FOO > # define F_OFD_FOO xyz > #endif > > This wouldn't do much. > > Also these should be only disable on 32bit if __USE_FILE_OFFSET64 is > not > defined. But you likely meant that here. > That's the usual way, but in this case we wouldn't have a fallback constant. You'd just get an error about F_OFD_* being undefined at build time, which I think is what we'd want here. It's better to fail to compile than to build a binary that passes a bogus struct into the kernel. > > The other option would be to fix glibc and the kernel to handle > > legacy > > struct flock with F_OFD_ cmd values. That would mean adding > > F_OFD_*64 > > command values and fixing glibc to swap them in appropriately. > > That's > > doable, but I'm not sure it's really worth it. We'd also have to > > think > > about how to handle the old kernel/new glibc case (and vice versa), > > and > > that probably won't be trivial. > > I do not think that this is worth the work either. > -- Jeff Layton <jlayton@poochiereds.net> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 13:14 ` Jeff Layton @ 2016-08-17 13:19 ` Cyril Hrubis 2016-08-17 13:34 ` Jeff Layton 0 siblings, 1 reply; 14+ messages in thread From: Cyril Hrubis @ 2016-08-17 13:19 UTC (permalink / raw) To: ltp Hi! > > Hmm, I do not think that this is a good idea. The usuall way how to > > handle missing constants are fallback definitions such as: > > > > #ifndef F_OFD_FOO > > # define F_OFD_FOO xyz > > #endif > > > > This wouldn't do much. > > > > Also these should be only disable on 32bit if __USE_FILE_OFFSET64 is > > not > > defined. But you likely meant that here. > > > > That's the usual way, but in this case we wouldn't have a fallback > constant. You'd just get an error about F_OFD_* being undefined at > build time, which I think is what we'd want here. It's better to fail > to compile than to build a binary that passes a bogus struct into the > kernel. You probably misunderstand what I was trying to say. If you look at the sources out there (for instance at https://codesearch.debian.net/) most of it has fallback definitions for F_OFD_* constants included in its own header files since these flags are relatively new. Not defining these would not accomplish anything. One option would be to define them to something invalid such as INT_MAX so that it's rejected by kernel on runtime. But I do not think this is very good idea either. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 13:19 ` Cyril Hrubis @ 2016-08-17 13:34 ` Jeff Layton 2016-08-17 13:34 ` Cyril Hrubis 0 siblings, 1 reply; 14+ messages in thread From: Jeff Layton @ 2016-08-17 13:34 UTC (permalink / raw) To: ltp On Wed, 2016-08-17 at 15:19 +0200, Cyril Hrubis wrote: > Hi! > > > > > > > > Hmm, I do not think that this is a good idea. The usuall way how to > > > handle missing constants are fallback definitions such as: > > > > > > #ifndef F_OFD_FOO > > > # define F_OFD_FOO xyz > > > #endif > > > > > > This wouldn't do much. > > > > > > Also these should be only disable on 32bit if __USE_FILE_OFFSET64 is > > > not > > > defined. But you likely meant that here. > > > > > > > That's the usual way, but in this case we wouldn't have a fallback > > constant. You'd just get an error about F_OFD_* being undefined at > > build time, which I think is what we'd want here. It's better to fail > > to compile than to build a binary that passes a bogus struct into the > > kernel. > > You probably misunderstand what I was trying to say. If you look at the > > sources out there (for instance at https://codesearch.debian.net/) most > of it has fallback definitions for F_OFD_* constants included in its own > header files since these flags are relatively new. Not defining these > would not accomplish anything. > > One option would be to define them to something invalid such as INT_MAX > so that it's rejected by kernel on runtime. But I do not think this is > very good idea either. > Yeah, not much we can do about people that define them on their own. If you do that, then you're basically saying "I know what I'm doing". Still, I think it's worthwhile to do this in glibc since we _can_ prevent this problem for folks who aren't doing that. -- Jeff Layton <jlayton@poochiereds.net> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 13:34 ` Jeff Layton @ 2016-08-17 13:34 ` Cyril Hrubis 0 siblings, 0 replies; 14+ messages in thread From: Cyril Hrubis @ 2016-08-17 13:34 UTC (permalink / raw) To: ltp Hi! > > You probably misunderstand what I was trying to say. If you look at the > > > sources out there (for instance at https://codesearch.debian.net/) most > > of it has fallback definitions for F_OFD_* constants included in its own > > header files since these flags are relatively new. Not defining these > > would not accomplish anything. > > > > One option would be to define them to something invalid such as INT_MAX > > so that it's rejected by kernel on runtime. But I do not think this is > > very good idea either. > > > > Yeah, not much we can do about people that define them on their own. If > you do that, then you're basically saying "I know what I'm doing". > > Still, I think it's worthwhile to do this in glibc since we _can_ > prevent this problem for folks who aren't doing that. Ok. Then this should be also paired with patch for the manual page that explains that these locks are only available with the _FILE_OFFSET_BITS=64. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-17 11:44 ` Jeff Layton 2016-08-17 11:53 ` Cyril Hrubis @ 2016-08-17 19:44 ` Michael Kerrisk 1 sibling, 0 replies; 14+ messages in thread From: Michael Kerrisk @ 2016-08-17 19:44 UTC (permalink / raw) To: ltp Hi Jeff, On 08/17/2016 11:44 PM, Jeff Layton wrote: > On Wed, 2016-08-17 at 10:10 +0200, Cyril Hrubis wrote: >> Hi! >>> >>> The way the kernel works is that if you call fcntl(), then you need to >>> pass in a struct flock. If you call fcntl64() then you need to pass in >>> a struct flock64. Of course this is only on 32-bit arches. On 64-bit, >>> it's there is no flock64 or fcntl64. >> >> This does not seem to be the case. >> >> It looks like kernel expect F_{SET,GET}LK to be 32bit for fcntl64() as >> well. It just calls do_fcntl() that casts the pointer to struct flock >> that seems to be defined with __kernel_off_t in the uapi headers which >> is alias to long. >> >> And the same in the compat implementation, there the F_{SET,GET}LK works >> with struct compat_flock that has 32bit off_t as well. >> >> Then we have the F_{SET,GET}LK64 that expect 64bit flock and the >> F_OFD_XXX behaves exactly same. As a matter of the fact they are handled >> mostly in the same branches of the switch() statements which lead me to >> belive that they were intended to be used with flock64 explicitly. >> >> Glibc does not seem to do much work here. The only thing it does is to >> switch between the F_{SET,GET}LK and F_{SET,GET}LK64 based on >> _FILE_OFFSET_BITS to match the off_t type in the flock structure. >> > > Thanks, I think I understand now. I think there are a couple of > potential fixes... > > The simplest thing is to do what you're suggesting and simply document > that F_OFD_* locks require large file offsets. If we do that though, > then I think we also ought to do something to ensure that the build > breaks if you try to use F_OFD_* commands without large offsets. > > The simplest way would be to put the F_OFD_* constant definitions under > "#ifdef __USE_FILE_OFFSET64", but I'm open to suggestions that would > make the compiler error out with a more helpful error message. > > The other option would be to fix glibc and the kernel to handle legacy > struct flock with F_OFD_ cmd values. That would mean adding F_OFD_*64 > command values and fixing glibc to swap them in appropriately. That's > doable, but I'm not sure it's really worth it. We'd also have to think > about how to handle the old kernel/new glibc case (and vice versa), and > that probably won't be trivial. > > I'm leaning toward option #1 here. I can cook up a patch for glibc if > you guys agree. > > Thoughts? Looking at the long picture, it seems to me that option 2 would be preferable, albeit more work. Thanks, Michael -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 2016-08-16 20:04 ` Michael Kerrisk 2016-08-16 23:41 ` Jeff Layton @ 2016-08-17 7:44 ` Cyril Hrubis 1 sibling, 0 replies; 14+ messages in thread From: Cyril Hrubis @ 2016-08-17 7:44 UTC (permalink / raw) To: ltp Hi! > > If we pass struct flock to the F_OFD_XXX fcntl() it will fail with > > EINVAL with a 32bit binary. That is because glibc uses fcntl64() by > > default but the struct flock uses 32bit off_t for 32bit binaries (unless > > _FILE_OFFSET_BITS=64) and kernel always expect flock64 for F_OFD_XXX in > > fcntl64(). Hence kernel will read some garbage that is a few bytes after > > the 32bit flock structure in this case which will likely end up with the > > syscall returning EINVAL. > > Okay -- I confirm the problem you report. I'm just not sure that the > patch below is the best fix. So, to summarize: Either we do that or we have to translate the flock{} to flock64{} at the runtime if F_OFD_XXX was the fcntl() cmd. However the problem is that we have no idea if _FILE_OFFSET_BITS was set or not once we reach fcntl.c in glibc. So the whole translation would have been put into the fcntl.h header into some ugly macro or we would have to do some trickery like passing down the sizeof(struct flock) as additional fcntl parameter. > One solution would be your patch below, but it feels wrong: on 64-bit > flock{} suffices, and is consistent with the traditional F_* operations. > An alternative would be a note in the man page that says something along > the lines that on 32-bit, one must compile with -D_FILE_OFFSET_BITS=64 > when using the F_OFD operations. That would be solution as well. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2016-08-17 19:44 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-08-16 11:55 [LTP] [PATCH] fcntl.2: F_OFD_XXX needs flock64 Cyril Hrubis 2016-08-16 14:34 ` Cyril Hrubis 2016-08-16 20:04 ` Michael Kerrisk 2016-08-16 23:41 ` Jeff Layton 2016-08-17 1:08 ` Michael Kerrisk 2016-08-17 8:10 ` Cyril Hrubis 2016-08-17 11:44 ` Jeff Layton 2016-08-17 11:53 ` Cyril Hrubis 2016-08-17 13:14 ` Jeff Layton 2016-08-17 13:19 ` Cyril Hrubis 2016-08-17 13:34 ` Jeff Layton 2016-08-17 13:34 ` Cyril Hrubis 2016-08-17 19:44 ` Michael Kerrisk 2016-08-17 7:44 ` Cyril Hrubis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox