setresuid, setreuid AIO, bug? where?

Paul Dufresne dufresnep at
Mon Mar 23 02:58:25 UTC 2009

While investigating Samba? bug:

I came on:

Well, I tested a bit the
program on my system:
Linux version 2.6.28-9-generic (buildd at palmer) (gcc version 4.3.3
(Ubuntu 4.3.3-5ubuntu2) ) #31-Ubuntu SMP Wed Mar 11 15:43:58 UTC 2009
(ubuntu Jaunty 32 bits), and seems to confirm the 'bug' with aio_uid.c
Compiled with 'gcc -lrt aio_uid.c' and then tested with:
sudo ./a.out test.txt

But the comment from a glibc developer:
made me thinks: Hey, don't they know at glibc that this is setreuid
that is in Posix standard,
not setresuid!?

So I downloaded the glibc-source package and came to the conclusion
that setresuid simply call the kernel as directly as possible:
.../glibc2.9/sysdeps/unix/sysv/linux/setresuid.c is:
__setresuid (uid_t ruid, uid_t euid, uid_t suid)
  return INLINE_SETXID_SYSCALL (setresuid, 3, ruid, euid, suid);

and #define INLINE_SETXID_SYSCALL(name, nr, args...) \
  INLINE_SYSCALL (name, nr, args)
inside .../glibc2.9/sysdeps/unix/setxid.h

So I thought, well, let's go see how setreuid is coded in glibc.
In .../glibc2.9/sysdeps/unix/sysv/linux/i386/setreuid.c I found what
seems to me like
quite a robust implementation:
#ifdef __NR_setreuid32
# if __ASSUME_32BITUIDS == 0
/* This variable is shared with all files that need to check for 32bit
   uids.  */
extern int __libc_missing_32bit_uids;
# endif
#endif /* __NR_setreuid32 */

__setreuid (uid_t ruid, uid_t euid)
  int result;

#if __ASSUME_32BITUIDS > 0
  result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid);
# ifdef __NR_setreuid32
  if (__libc_missing_32bit_uids <= 0)
      int saved_errno = errno;

      result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid);

      if (result == 0)
	goto out;
      if (errno != ENOSYS)
	return result;

      __set_errno (saved_errno);
      __libc_missing_32bit_uids = 1;
# endif /* __NR_setreuid32 */
  if (((ruid + 1) > (uid_t) ((__kernel_uid_t) -1U))
      || ((euid + 1) > (uid_t) ((__kernel_uid_t) -1U)))
      __set_errno (EINVAL);
      return -1;

  result = INLINE_SETXID_SYSCALL (setreuid, 2, ruid, euid);
# ifdef __NR_setreuid32
# endif

  return result;

Well, I have no idea which implementation is call on my system.

But the conclusion that come to my mind, is perhaps the AIO and
setresuid problem, is inside the kernel, not inside glibc, as the bug
reporter at Red Hat suggest.

Samba seems to have taken the decision to switch to using setreuid,
after this bug report.

I wish a much competent than me could take a look at this issue,
figure out if there is no
problem with (I don't
understand really, but man usleep suggest that the interaction with
alarm might be problematic).

I am not much use to system programming under Linux, and would like
someone more competent than myself to have a look, and eventually if
it is a bug in the kernel, submit it upstream.

More information about the Ubuntu-devel-discuss mailing list