* [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) @ 2009-04-21 8:24 Arnaud Patard 2009-04-21 8:36 ` Laurent Desnogues 2009-04-21 12:34 ` Riku Voipio 0 siblings, 2 replies; 7+ messages in thread From: Arnaud Patard @ 2009-04-21 8:24 UTC (permalink / raw) To: qemu-devel [-- Attachment #1: Type: text/plain, Size: 369 bytes --] Don't use the glibc function for utimensat because glibc returns -EINVAL if the path is null which is a different behaviour with the syscall. path can be null because internally the glibc is using utimensat with path null (for instance, see __futimes in sysdeps/unix/sysv/linux/futimes.c in glibc tree). Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org> --- [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: utimensat.patch --] [-- Type: text/x-diff, Size: 1025 bytes --] diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b6dc6cc..6959da0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -412,13 +412,6 @@ static int sys_unlinkat(int dirfd, const char *pathname, int flags) return (unlinkat(dirfd, pathname, flags)); } #endif -#ifdef TARGET_NR_utimensat -static int sys_utimensat(int dirfd, const char *pathname, - const struct timespec times[2], int flags) -{ - return (utimensat(dirfd, pathname, times, flags)); -} -#endif #else /* !CONFIG_ATFILE */ /* @@ -478,12 +471,12 @@ _syscall3(int,sys_symlinkat,const char *,oldpath, #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags) #endif +#endif /* CONFIG_ATFILE */ #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, const struct timespec *,tsp,int,flags) #endif -#endif /* CONFIG_ATFILE */ #ifdef CONFIG_INOTIFY #include <sys/inotify.h> ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) 2009-04-21 8:24 [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) Arnaud Patard @ 2009-04-21 8:36 ` Laurent Desnogues 2009-04-21 12:34 ` Riku Voipio 1 sibling, 0 replies; 7+ messages in thread From: Laurent Desnogues @ 2009-04-21 8:36 UTC (permalink / raw) To: Arnaud Patard; +Cc: qemu-devel On Tue, Apr 21, 2009 at 10:24 AM, Arnaud Patard <arnaud.patard@rtp-net.org> wrote: > > > Don't use the glibc function for utimensat because glibc returns -EINVAL > if the path is null which is a different behaviour with the syscall. > path can be null because internally the glibc is using utimensat with > path null (for instance, see __futimes in > sysdeps/unix/sysv/linux/futimes.c in glibc tree). > > > Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org> Acked-by: Laurent Desnogues <laurent.desnogues@gmail.com> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) 2009-04-21 8:24 [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) Arnaud Patard 2009-04-21 8:36 ` Laurent Desnogues @ 2009-04-21 12:34 ` Riku Voipio 2009-04-21 14:42 ` Jamie Lokier 2009-04-21 16:09 ` Martin Mohring 1 sibling, 2 replies; 7+ messages in thread From: Riku Voipio @ 2009-04-21 12:34 UTC (permalink / raw) To: Arnaud Patard; +Cc: laurent.desnogues, qemu-devel On Tue, Apr 21, 2009 at 10:24:03AM +0200, Arnaud Patard wrote: > Don't use the glibc function for utimensat because glibc returns -EINVAL > if the path is null which is a different behaviour with the syscall. > path can be null because internally the glibc is using utimensat with > path null (for instance, see __futimes in > sysdeps/unix/sysv/linux/futimes.c in glibc tree). Soo.. glibc uses utimensat to implement futimens, but doesn't allow applications to use utimensat in the same way. What a mess. But if we are to go towards using libc calls, your patch is a step backwards. In case pathname is null, we can use futimens. commit 0f34ff059fb9ad6e8c8fa5161d9d17265286bb62 Author: Riku Voipio <riku.voipio@iki.fi> Date: Tue Apr 21 15:01:51 2009 +0300 linux-user: fix utimensat when used as futimens The glibc function for utimensat glibc returns -EINVAL when the path is null which is a different behaviour with the syscall. path can be null because internally the glibc is using utimensat with path null when implmenting futimens. If path is null, call futimes instead. diff --git a/configure b/configure index 08df436..fc980a4 100755 --- a/configure +++ b/configure @@ -1208,6 +1208,25 @@ EOF fi fi +# check if utimensat and futimens are supported +utimens=no +cat > $TMPC << EOF +#define _ATFILE_SOURCE +#define _GNU_SOURCE +#include <stddef.h> +#include <fcntl.h> + +int main(void) +{ + utimensat(AT_FDCWD, "foo", NULL, 0); + futimens(0, NULL); + return 0; +} +EOF +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + utimens=yes +fi + # Check if tools are available to build documentation. if [ -x "`which texi2html 2>/dev/null`" ] && \ [ -x "`which pod2man 2>/dev/null`" ]; then @@ -1604,6 +1623,9 @@ fi if test "$atfile" = "yes" ; then echo "#define CONFIG_ATFILE 1" >> $config_h fi +if test "$utimens" = "yes" ; then + echo "#define CONFIG_UTIMENSAT 1" >> $config_h +fi if test "$inotify" = "yes" ; then echo "#define CONFIG_INOTIFY 1" >> $config_h fi diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 408ccc6..4dad5c1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -406,13 +406,6 @@ static int sys_unlinkat(int dirfd, const char *pathname, int flags) return (unlinkat(dirfd, pathname, flags)); } #endif -#ifdef TARGET_NR_utimensat -static int sys_utimensat(int dirfd, const char *pathname, - const struct timespec times[2], int flags) -{ - return (utimensat(dirfd, pathname, times, flags)); -} -#endif #else /* !CONFIG_ATFILE */ /* @@ -476,12 +469,24 @@ _syscall3(int,sys_symlinkat,const char *,oldpath, #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags) #endif + +#endif /* CONFIG_ATFILE */ + +#ifdef CONFIG_UTIMENSAT +static int sys_utimensat(int dirfd, const char *pathname, + const struct timespec times[2], int flags) +{ + if (pathname == NULL) + return futimens(dirfd, times); + else + return utimensat(dirfd, pathname, times, flags); +} +#else #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, const struct timespec *,tsp,int,flags) #endif - -#endif /* CONFIG_ATFILE */ +#endif /* CONFIG_UTIMENSAT */ #ifdef CONFIG_INOTIFY #include <sys/inotify.h> ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) 2009-04-21 12:34 ` Riku Voipio @ 2009-04-21 14:42 ` Jamie Lokier 2009-04-21 16:09 ` Martin Mohring 1 sibling, 0 replies; 7+ messages in thread From: Jamie Lokier @ 2009-04-21 14:42 UTC (permalink / raw) To: Riku Voipio; +Cc: laurent.desnogues, qemu-devel, Arnaud Patard Riku Voipio wrote: > Soo.. glibc uses utimensat to implement futimens, but doesn't allow > applications to use utimensat in the same way. What a mess. It protects against apps passing in NULL path due to a bug and touching the directory by accident. A minor bit of protection indeed. > But if we are to go towards using libc calls, your patch is a step > backwards. In case pathname is null, we can use futimens. I agree, good idea. -- Jamie ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) 2009-04-21 12:34 ` Riku Voipio 2009-04-21 14:42 ` Jamie Lokier @ 2009-04-21 16:09 ` Martin Mohring 2009-04-21 16:38 ` Martin Mohring 1 sibling, 1 reply; 7+ messages in thread From: Martin Mohring @ 2009-04-21 16:09 UTC (permalink / raw) To: Riku Voipio; +Cc: laurent.desnogues, qemu-devel, Arnaud Patard i found another related case it seems: when i call in a chroot under arm with qemu user mode: $ touch /var/log/wtmp the resulting file has a date/time of 1.1.1970, although the clock is correct in the system. calling $ touch /var/log/wtmp /var/run/utmp /var/log/btmp /bin/touch: setting times of `/var/run/utmp': Invalid argument /bin/touch: setting times of `/var/log/btmp': Invalid argument results in the invalid argutment error. I ll currently check which syscalls are involved here. the time of 1.1.1970 looks to me like a wrongly passed argument (of ==0). Riku Voipio wrote: > On Tue, Apr 21, 2009 at 10:24:03AM +0200, Arnaud Patard wrote: > >> Don't use the glibc function for utimensat because glibc returns -EINVAL >> if the path is null which is a different behaviour with the syscall. >> path can be null because internally the glibc is using utimensat with >> path null (for instance, see __futimes in >> sysdeps/unix/sysv/linux/futimes.c in glibc tree). >> > > Soo.. glibc uses utimensat to implement futimens, but doesn't allow > applications to use utimensat in the same way. What a mess. > > But if we are to go towards using libc calls, your patch is a step > backwards. In case pathname is null, we can use futimens. > > > commit 0f34ff059fb9ad6e8c8fa5161d9d17265286bb62 > Author: Riku Voipio <riku.voipio@iki.fi> > Date: Tue Apr 21 15:01:51 2009 +0300 > > linux-user: fix utimensat when used as futimens > > The glibc function for utimensat glibc returns -EINVAL when the path is null > which is a different behaviour with the syscall. > > path can be null because internally the glibc is using utimensat with > path null when implmenting futimens. If path is null, call futimes > instead. > > diff --git a/configure b/configure > index 08df436..fc980a4 100755 > --- a/configure > +++ b/configure > @@ -1208,6 +1208,25 @@ EOF > fi > fi > > +# check if utimensat and futimens are supported > +utimens=no > +cat > $TMPC << EOF > +#define _ATFILE_SOURCE > +#define _GNU_SOURCE > +#include <stddef.h> > +#include <fcntl.h> > + > +int main(void) > +{ > + utimensat(AT_FDCWD, "foo", NULL, 0); > + futimens(0, NULL); > + return 0; > +} > +EOF > +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then > + utimens=yes > +fi > + > # Check if tools are available to build documentation. > if [ -x "`which texi2html 2>/dev/null`" ] && \ > [ -x "`which pod2man 2>/dev/null`" ]; then > @@ -1604,6 +1623,9 @@ fi > if test "$atfile" = "yes" ; then > echo "#define CONFIG_ATFILE 1" >> $config_h > fi > +if test "$utimens" = "yes" ; then > + echo "#define CONFIG_UTIMENSAT 1" >> $config_h > +fi > if test "$inotify" = "yes" ; then > echo "#define CONFIG_INOTIFY 1" >> $config_h > fi > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 408ccc6..4dad5c1 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -406,13 +406,6 @@ static int sys_unlinkat(int dirfd, const char *pathname, int flags) > return (unlinkat(dirfd, pathname, flags)); > } > #endif > -#ifdef TARGET_NR_utimensat > -static int sys_utimensat(int dirfd, const char *pathname, > - const struct timespec times[2], int flags) > -{ > - return (utimensat(dirfd, pathname, times, flags)); > -} > -#endif > #else /* !CONFIG_ATFILE */ > > /* > @@ -476,12 +469,24 @@ _syscall3(int,sys_symlinkat,const char *,oldpath, > #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) > _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags) > #endif > + > +#endif /* CONFIG_ATFILE */ > + > +#ifdef CONFIG_UTIMENSAT > +static int sys_utimensat(int dirfd, const char *pathname, > + const struct timespec times[2], int flags) > +{ > + if (pathname == NULL) > + return futimens(dirfd, times); > + else > + return utimensat(dirfd, pathname, times, flags); > +} > +#else > #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) > _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, > const struct timespec *,tsp,int,flags) > #endif > - > -#endif /* CONFIG_ATFILE */ > +#endif /* CONFIG_UTIMENSAT */ > > #ifdef CONFIG_INOTIFY > #include <sys/inotify.h> > > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) 2009-04-21 16:09 ` Martin Mohring @ 2009-04-21 16:38 ` Martin Mohring 2009-04-21 18:18 ` Riku Voipio 0 siblings, 1 reply; 7+ messages in thread From: Martin Mohring @ 2009-04-21 16:38 UTC (permalink / raw) To: Martin Mohring; +Cc: laurent.desnogues, Riku Voipio, qemu-devel, Arnaud Patard Martin Mohring wrote: > i found another related case it seems: > > when i call in a chroot under arm with qemu user mode: > > $ touch /var/log/wtmp > > the resulting file has a date/time of 1.1.1970, although the clock is > correct in the system. > > calling > > $ touch /var/log/wtmp /var/run/utmp /var/log/btmp > /bin/touch: setting times of `/var/run/utmp': Invalid argument > /bin/touch: setting times of `/var/log/btmp': Invalid argument > > results in the invalid argutment error. I ll currently check which > syscalls are involved here. > the time of 1.1.1970 looks to me like a wrongly passed argument (of ==0). > a trace of this: 27374 open("/var/log/wtmp",0x20941,0666) = 3 27374 dup2(3,0,3,0,0,1109324328) = 0 27374 close(3) = 0 27374 utimensat(0,"(null)",(nil),0) = 0 27374 close(0) = 0 27374 open("/var/run/utmp",0x20941,0666) = 0 27374 utimensat(0,"(null)",(nil),0) = -1 errno=22 (Invalid argument) 27374 close(0) = 0 27374 write(2,0x4007d430,12)/bin/touch: = 12 27374 write(2,0x4007d408,32)setting times of `/var/run/utmp' = 32 27374 write(2,0x4007cfd0,18): Invalid argument = 18 27374 write(2,0x4007d3d8,1) = 1 27374 open("/var/log/btmp",0x20941,0666) = 0 27374 utimensat(0,"(null)",(nil),0) = -1 errno=22 (Invalid argument) 27374 close(0) = 0 27374 write(2,0x4007d430,12)/bin/touch: = 12 27374 write(2,0x4007d408,32)setting times of `/var/log/btmp' = 32 27374 write(2,0x4007cfd0,18): Invalid argument = 18 27374 write(2,0x4007d3d8,1) = 1 27374 close(1) = 0 27374 close(2) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) 2009-04-21 16:38 ` Martin Mohring @ 2009-04-21 18:18 ` Riku Voipio 0 siblings, 0 replies; 7+ messages in thread From: Riku Voipio @ 2009-04-21 18:18 UTC (permalink / raw) To: Martin Mohring; +Cc: laurent.desnogues, qemu-devel, Arnaud Patard On Tue, Apr 21, 2009 at 06:38:17PM +0200, Martin Mohring wrote: > > results in the invalid argutment error. I ll currently check which > > syscalls are involved here. > > the time of 1.1.1970 looks to me like a wrongly passed argument (of ==0). no, NULL is what is supposed to be passed. try stracing a normal host /bin/touch. > 27374 open("/var/log/wtmp",0x20941,0666) = 3 > 27374 dup2(3,0,3,0,0,1109324328) = 0 > 27374 close(3) = 0 > 27374 utimensat(0,"(null)",(nil),0) = 0 > 27374 close(0) = 0 > 27374 open("/var/run/utmp",0x20941,0666) = 0 > 27374 utimensat(0,"(null)",(nil),0) = -1 errno=22 (Invalid argument) It is unclear what svn revision you are using qemu, and/or if you are using any of the patches in this thread. The patch I sent earlier, should fix the invalid arg issue. As for the 1970 issue, try this patch. commit 7f7e93aabde6b8f0e4a1a05537145efa9ed0156b Author: Riku Voipio <riku.voipio@iki.fi> Date: Tue Apr 21 20:37:01 2009 +0300 linux-user: fix utimensat with NULL timespec Don't try to copy timespec from user if it is NULL. diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e19e289..0049840 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6674,17 +6674,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) case TARGET_NR_utimensat: { - struct timespec ts[2]; - target_to_host_timespec(ts, arg3); - target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); + struct timespec *tsp, ts[2]; + if (!arg3) { + tsp = NULL; + } else { + target_to_host_timespec(ts, arg3); + target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); + tsp = ts; + } if (!arg2) - ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4)); + ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4)); else { if (!(p = lock_user_string(arg2))) { ret = -TARGET_EFAULT; goto fail; } - ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4)); + ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4)); unlock_user(p, arg2, 0); } } ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-04-21 18:18 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-04-21 8:24 [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) Arnaud Patard 2009-04-21 8:36 ` Laurent Desnogues 2009-04-21 12:34 ` Riku Voipio 2009-04-21 14:42 ` Jamie Lokier 2009-04-21 16:09 ` Martin Mohring 2009-04-21 16:38 ` Martin Mohring 2009-04-21 18:18 ` Riku Voipio
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).