[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#183694: problem of 32 bit uid or gid in glibc



Package: libc6
Version: 2.2.5-11.2, 2.3.1-14
Severity: normal


 Running samba as file server on i686 under Debian Woody.
When client access shared file on uid of 65535 by Windows2k
and open the property of shared file, ACL information can't
refernce. This means that it happen error in samba.
Samba works good on uid less than 65535.

 I think that this case is the next cause.
For example when geteuid() is called as ERRNO=ENOSYS,
library set 1 for __libc_missing_32bit_uids.


geteuid.c :

~~~~~~~~
      result = INLINE_SYSCALL (geteuid32, 0);
      if (result == 0 || errno != ENOSYS)
 return result;
      __set_errno (saved_errno);
      __libc_missing_32bit_uids = 1;

~~~~~~~~

and then if seteuid() is called on uid more than 65535,
-1 is returned and errno is set EINVAL 

It happen error in samba for this reason.


setreuid.c <- seteuid() :

~~~~~~~~
# ifdef __NR_setreuid32
  if (__libc_missing_32bit_uids <= 0)
    {
      int result;
      int saved_errno = errno;

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

      if (result == 0 || 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;
    }
  return INLINE_SYSCALL (setreuid, 2, ruid, euid);

~~~~~~~~

 There is following function that substitute 1
for __libc_missing_32bit_uids.

getegid.c
geteuid.c
getgid.c
getgroups.c
getuid.c
setfsgid.c
setfsuid.c


 Show a easy test case.

$ su -
# cat > idt.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

#define UID 65535

main()
{
	int ret;
	unsigned int euid;

	errno=ENOSYS;
	if( seteuid(UID) == -1 )
		exit(-1);

	euid = geteuid();
	printf("geteuid() errno=%d uid=%d\n", errno, euid);
	ret = seteuid(UID);
	printf("seteuid() errno=%d ret=%d\n", errno, ret);
	
}
# cc -o idt idt.c
# ./idt
geteuid() errno=38 uid=65535
seteuid() errno=22 ret=-1
#


 I think that this problem will resolve by following code.

original code:

  if (__libc_missing_32bit_uids <= 0)
    {
      int result;
      int saved_errno = errno;

      result = INLINE_SYSCALL (geteuid32, 0);
      if (result == 0 || errno != ENOSYS)
	return result;

      __set_errno (saved_errno);
      __libc_missing_32bit_uids = 1;
    }


modify code:
 Perhaps, following code would work correctly.
but it isn't perfect answer.
Because man description that geteuid() are always successful,
and so -1 isn't error return.

	if (__libc_missing_32bit_uids <= 0)
	{
	    int result;
	    int save_errno = errno;

	    result = INLINE_SYSCALL (geteuid32, 0);
	    if (result == -1 && errno == ENOSYS)
	      __libc_missing_32bit_uids = 1;
	    else
	      __libc_missing_32bit_uids = 0;
	    __set_errno(save_errno);
	}
	if (__libc_missing_32bit_uids <= 0)
	  {
	    return result;
	  }


 In case of linux, if kernel version is more than 2.3.39,
we will be able to avoid problem that rebuild glibc with
--enable-kernel on configure option.
 Bucause __ASSUME_32BITUIDS is defined 1 and 32bit function
always is called.


-- 
kakuma fumihiko <kakuma@valinux.co.jp>




Reply to: