mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: musl@lists.openwall.com
Subject: Re: [UGLY PATCH v3] Support for no-legacy-syscalls archs
Date: Thu, 29 May 2014 17:46:21 -0400	[thread overview]
Message-ID: <20140529214621.GQ507@brightrain.aerifal.cx> (raw)
In-Reply-To: <20140527052625.GC507@brightrain.aerifal.cx>

On Tue, May 27, 2014 at 01:26:25AM -0400, Rich Felker wrote:
> diff --git a/src/exit/exit.c b/src/exit/exit.c
> index 353f50b..6ac90c3 100644
> --- a/src/exit/exit.c
> +++ b/src/exit/exit.c
> @@ -1,5 +1,6 @@
>  #include <stdlib.h>
>  #include <stdint.h>
> +#include "futex.h"
>  #include "libc.h"
>  #include "atomic.h"
>  #include "syscall.h"
> @@ -24,7 +25,12 @@ _Noreturn void exit(int code)
>  	static int lock;
>  
>  	/* If more than one thread calls exit, hang until _Exit ends it all */
> -	while (a_swap(&lock, 1)) __syscall(SYS_pause);
> +	while (a_swap(&lock, 1))
> +#ifdef SYS_pausex
> +		__syscall(SYS_pause);
> +#else
> +		__syscall(SYS_futex, &lock, FUTEX_WAIT, 1, 0);
> +#endif

Removed this change simply by dropping the code (see commit
2e55da911896a91e95b24ab5dc8a9d9b0718f4de).

> diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c
> index 08644f5..6fa33cb 100644
> --- a/src/process/posix_spawn.c
> +++ b/src/process/posix_spawn.c
> @@ -22,6 +22,18 @@ struct args {
>  
>  void __get_handler_set(sigset_t *);
>  
> +static int do_dup2(int old, int new)
> +{
> +	int r;
> +#ifdef SYS_dup2
> +	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
> +#else
> +	while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY);
> +	if (r==-EINVAL && old==new) return new;
> +#endif
> +	return r;
> +}
> +

This is overkill; I mistakenly thought the use of dup2 in posix_spawn
was missing the EBUSY check and loop and added all this mess. But the
EBUSY condition cannot happen in a single-threaded process that does
not share (CLONE_FILES) its descriptor table.

In fact, it seems like the EBUSY condition might be something we can
drop completely from dup2.c and dup3.c too. I'm not 100% sure yet but
it looks like it can only happen when the application invokes UB by
misusing dup2/dup3 in a multithreaded process when the destination
descriptor is not already known by the caller to be occupied.

> diff --git a/src/select/select.c b/src/select/select.c
> index f93597b..7b5f6dc 100644
> --- a/src/select/select.c
> +++ b/src/select/select.c
> @@ -1,8 +1,26 @@
>  #include <sys/select.h>
> +#include <signal.h>
> +#include <stdint.h>
> +#include <errno.h>
>  #include "syscall.h"
>  #include "libc.h"
>  
>  int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
>  {
> +#ifdef SYS_select
>  	return syscall_cp(SYS_select, n, rfds, wfds, efds, tv);
> +#else
> +	syscall_arg_t data[2] = { 0, _NSIG/8 };
> +	struct timespec ts;
> +	if (tv) {
> +		if (tv->tv_sec < 0 || tv->tv_usec < 0)
> +			return __syscall_ret(-EINVAL);
> +		time_t extra_secs = tv->tv_usec / 1000000;
> +		ts.tv_nsec = tv->tv_usec % 1000000 * 1000;
> +		const time_t max_time = (1ULL<<8*sizeof(time_t)-1)-1;
> +		ts.tv_sec = extra_secs > max_time - tv->tv_sec ?
> +			max_time : tv->tv_sec + extra_secs;
> +	}
> +	return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, tv ? &ts : 0, data);
> +#endif

This is a lot uglier than I'd prefer, but I don't see any way to
improve it. Blame the kernel folks...

>  }
> diff --git a/src/stat/chmod.c b/src/stat/chmod.c
> index beb66e5..d4f53c5 100644
> --- a/src/stat/chmod.c
> +++ b/src/stat/chmod.c
> @@ -1,7 +1,12 @@
>  #include <sys/stat.h>
> +#include <fcntl.h>
>  #include "syscall.h"
>  
>  int chmod(const char *path, mode_t mode)
>  {
> +#ifdef SYS_chmod
>  	return syscall(SYS_chmod, path, mode);
> +#else
> +	return syscall(SYS_fchmodat, AT_FDCWD, path, mode);
> +#endif
>  }
> diff --git a/src/stat/fchmod.c b/src/stat/fchmod.c
> index 6d28141..93e1b64 100644
> --- a/src/stat/fchmod.c
> +++ b/src/stat/fchmod.c
> @@ -13,5 +13,9 @@ int fchmod(int fd, mode_t mode)
>  
>  	char buf[15+3*sizeof(int)];
>  	__procfdname(buf, fd);
> +#ifdef SYS_chmod
>  	return syscall(SYS_chmod, buf, mode);
> +#else
> +	return syscall(SYS_fchmodat, AT_FDCWD, buf, mode);
> +#endif
>  }
> diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c
> index 12e7ff0..52029ec 100644
> --- a/src/stat/fchmodat.c
> +++ b/src/stat/fchmodat.c
> @@ -29,7 +29,7 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
>  
>  	__procfdname(proc, fd2);
>  	if (!(ret = __syscall(SYS_stat, proc, &st)) && !S_ISLNK(st.st_mode))
> -		ret = __syscall(SYS_chmod, proc, mode);
> +		ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
>  
>  	__syscall(SYS_close, fd2);
>  	return __syscall_ret(ret);
> diff --git a/src/stat/futimesat.c b/src/stat/futimesat.c
> index dbefc84..5990aa6 100644
> --- a/src/stat/futimesat.c
> +++ b/src/stat/futimesat.c
> @@ -1,10 +1,23 @@
>  #define _GNU_SOURCE
>  #include <sys/time.h>
> +#include <sys/stat.h>
> +#include <errno.h>
>  #include "syscall.h"
> +#include "libc.h"
>  
> -#ifdef SYS_futimesat
> -int futimesat(int dirfd, const char *pathname, const struct timeval times[2])
> +int __futimesat(int dirfd, const char *pathname, const struct timeval times[2])
>  {
> -	return syscall(SYS_futimesat, dirfd, pathname, times);
> +	struct timespec ts[2];
> +	if (times) {
> +		int i;
> +		for (i=0; i<2; i++) {
> +			if (times[i].tv_usec >= 1000000U)

I think there's a bug here; whether comparison against 1000000U will
promote the LHS to unsigned depends on the definition of suseconds_t.

> diff --git a/src/stat/utimensat.c b/src/stat/utimensat.c
> index 929698b..abc8d74 100644
> --- a/src/stat/utimensat.c
> +++ b/src/stat/utimensat.c
> @@ -1,7 +1,40 @@
>  #include <sys/stat.h>
> +#include <sys/time.h>
> +#include <fcntl.h>
> +#include <errno.h>
>  #include "syscall.h"
>  
>  int utimensat(int fd, const char *path, const struct timespec times[2], int flags)
>  {
> -	return syscall(SYS_utimensat, fd, path, times, flags);
> +	int r = __syscall(SYS_utimensat, fd, path, times, flags);
> +	if (r != -ENOSYS || flags) return __syscall_ret(r);
> +

Not a big deal, but this check can be moved inside the #ifdef:

> +#ifdef SYS_futimesat
> [...]
> 
> diff --git a/src/unistd/dup2.c b/src/unistd/dup2.c
> index 87a0d44..ed04a89 100644
> --- a/src/unistd/dup2.c
> +++ b/src/unistd/dup2.c
> @@ -5,6 +5,11 @@
>  int dup2(int old, int new)
>  {
>  	int r;
> +#ifdef SYS_dup2
>  	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
> +#else
> +	while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY);
> +	if (r==-EINVAL && old==new) return new;
> +#endif

Sadly this implementation is not correct since the kernel checks for
EINVAL before EBADF; it causes dup2(fd,fd) to always report success,
even if fd is not a valid file descriptor. So I think we really need
an ugly check for validity first...

Rich


  parent reply	other threads:[~2014-05-29 21:46 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-25  5:42 [UGLY PATCH] " Rich Felker
2014-05-25  9:52 ` Szabolcs Nagy
2014-05-25  9:57   ` Justin Cormack
2014-05-25 11:45   ` Rich Felker
2014-05-26  4:28 ` Rich Felker
2014-05-26 18:40 ` [UGLY PATCH v2] " Rich Felker
2014-05-26 21:13   ` Szabolcs Nagy
2014-05-26 21:54     ` Rich Felker
2014-05-26 22:39       ` Szabolcs Nagy
2014-05-26 22:46         ` Rich Felker
2014-05-27  5:26 ` [UGLY PATCH v3] " Rich Felker
2014-05-27 11:29   ` Szabolcs Nagy
2014-05-27 19:01     ` Rich Felker
2014-05-29 21:46   ` Rich Felker [this message]
2014-05-29 23:04   ` Rich Felker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140529214621.GQ507@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

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).