[OpenIndiana-discuss] Solaris privileges and seteuid()

Mohamed Khalfella khalfella at gmail.com
Thu Aug 16 00:04:19 UTC 2012


First of all, I am not expert in Openindiana but if I were you I would try
using dtrace to show which function get called in response to fchown
syscall (I assume you are not running a highly loaded production system yet
so we can enable fbt:::: safely)

#!/usr/sbin/dtrace -s
#pragma D option flowindent

syscall::fchown:entry
/execname == "EXECNAME"/
{
    self->follow = 1;
}

syscall::fchown:return
{
    self->follow = 0;
    trace(arg1);
}

fbt:::entry
/self->follow/
{
}

fbt:::return
/self->follow/
{
    trace(arg1);
}

You can use the above with both your example that succeeds and the file
server that fails (change EXECNAME appropriately), then you will be able to
pin point which function bites you off. Finally, a look at illumos source
code should reveal the main reason behind this behaviur.


On Wed, Aug 15, 2012 at 4:38 PM, Frank Lahm <franklahm at gmail.com> wrote:

> Hi all,
>
> I'm having difficulties with Solaris privileges and seteuid().
>
> I have a forking daemon process running as root. The process is afpd
> from the Netatalk (OS AFP fileserver). The main afpd process accepts
> network connections, authenticates users (through PAM) and, forks and
> runs seteuid(USER).
> Occasionally the process calls seteuid(0) to execute priviliged
> operations and then goes seteuid(USER) back again.
>
> This all works find with local Solaris users. Now I've added Active
> Directory to the mix (smbadm join, nss_ad, pam_krb5). Works fine
> execpt for one issue which is a result of the following idmap
> restriction
>
>    man idmap
>    ...
>      To prevent aliasing problems, all file systems, archive  and
>      backup  formats,  and  protocols  must store SIDs or map all
>      UIDs and GIDs in the 2^31 to 2^32 - 2 range  to  the  nobody
>      user and group.
>    ...
>
> This means any file created by an afpd process (Solaris CIFS/NFS don't
> have this issue) running with the effective uid of an AD user is
> created with and owner/group of nobody:
>
>   root at oi:~# ps -elf | grep aduser
>    0 S aduser at a 12440 12193 0  40 20  ?   4518  ? 15:03:12 ?  0:00
> /usr/local/netatalk/sbin/afpd -d -F
>
>   root at oi:~# pcred 12440
>   12440:  euid=2147500125 ruid=0 suid=0  egid=2147491842 rgid=0 sgid=0
>
>   root at oi:~# getent passwd aduser at ad.hh.netafp.com
>   aduser at ad.hh.netafp.com:x:2147500125:2147491842:AD User::/bin/sh
>
> ...create file via AFP (touch /Volumes/test/afpfile1 on a Mac)...
>
>   root at oi:~# ls -l /Volumes/test/afpfile1
>   -rw-rw-rw-   1 nobody   nobody         0 Aug 15 15:04
> /Volumes/test/afpfile1
>
> The file "afpfile1" was created by the afpd process [12440] with a
> call to open(...O_CREAT...).
>
> I know from writing a simple test program (see below) that a possible
> workaround to enforce owner/group for file is just calling chown on
> them. This works with chown(1)
>
>   root at oi:~# chown aduser at ad.hh.netafp.com /Volumes/test/afpfile1
>   root at oi:~# ls -l /Volumes/test/afpfile1
>   -rw-rw-rw-   1 aduser at ad.hh.netafp.com nobody         0 Aug 15 15:04
> /Volumes/test/afpfile1
>
> ...and it works in the test program, unfortunately it doesn't work for
> afpd, all I get is EPERM (missing privilege file_chown_self). As I'm
> wrapping the fchwon call between seteuid(0) and seteuid(USER) and I've
> also verified that PAS (privilege awareness state) for the process is
> 0 by call getpflags(PRIV_AWARE) before the call to chmod:
>
> Code:
>     LOG(log_note, logtype_afpd, "afp_createfile: PAS: %s",
> getpflags(PRIV_AWARE) ? "PRIV_AWARE" : "not PRIV_AWARE");
>
> Log:
>     Aug 15 15:06:42.083590 afpd[12440] {file.c:732} (N:AFPDaemon):
> afp_createfile: PAS: not PRIV_AWARE
>
> truss shows:
>
>   root at oi:~# truss -v all -t fchown,seteuid -p 12440
>   seteuid(0)                                      = 0
>   fchown(10, -2147467171, -2147475454)            Err#1 EPERM
> [file_chown_self]
>   seteuid(2147500125)                             = 0
>
> The negative uid and gid for fchown are ok, truss interprets the
> ephemeral ids (defined to be >0x8000000) as negative numbers.
>
>   root at oi:~# ppriv 12440
>   12440:  /usr/local/netatalk/sbin/afpd -d -F
> /usr/local/netatalk/etc/afp.conf
>   flags = <none>
>           E: basic
>           I: basic
>           P: all
>           L: all
>
> No matter what I try (increasing privileges for the process with eg
> ppriv -s EIPL=all PID), it always fails with EPERM which strikes me as
> it is demonstratably doing the fchown() with an effective uid of 0.
>
> I highly appreciate any insight or pointers. There's a budget for paid
> consulting, you can also contact me by PM if your interested and you
> think you can help.
>
> Thank you!
> -f
>
> ---8<---
> /*
>  * gcc -o seteuid seteuid.c
>  */
>
> #define _FILE_OFFSET_BITS 64
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <sys/types.h>
> #include <fcntl.h>
> #include <sys/stat.h>
> #include <errno.h>
> #include <pwd.h>
>
> #define ERROR(msg) do { perror(msg); exit(1); } while (0)
>
> int wait_for_key(void)
> {
>     printf(" [Press RETURN to continue...]");
>     getchar();
> }
>
> int main (int argc, char **argv)
> {
>     struct stat st;
>     const char *name, *file;
>     struct passwd *pwd;
>     int fd;
>
>     if (argc < 3) {
>         printf("usage: %s USERNAME FILENAME\n", argv[0]);
>         exit(1);
>     }
>
>     name = argv[1];
>     file = argv[2];
>
>     if (getuid() != 0) {
>         printf("Must be run with uid 0 (root)\n");
>         exit(1);
>     }
>
>     if ((pwd = getpwnam(name)) == NULL)
>         ERROR("getpwnam");
>
>     printf("name: %s, uid: %u\n", name, pwd->pw_uid);
>
>     printf("switching effective uid to %u", pwd->pw_uid);
>     wait_for_key();
>
>     if (seteuid(pwd->pw_uid) != 0)
>         ERROR("seteuid");
>
>     printf("creating file ...");
>     wait_for_key();
>
>     if ((fd = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
>         ERROR("creat");
>
>     if (fstat(fd, &st) != 0)
>         ERROR("fstat");
>
>     printf("file owner uid: %u\n", st.st_uid);
>
>     printf("switch effective uid back to 0 (root) ...");
>     wait_for_key();
>
>     if (seteuid(0) != 0)
>         ERROR("seteuid");
>
>     printf("Try to change owner of testfile to %u", pwd->pw_uid);
>     wait_for_key();
>
>     if (fchown(fd, pwd->pw_uid) != 0)
>         ERROR("fchown");
>
>     close(fd);
>     return 0;
> }
> ---8<---
>
> _______________________________________________
> OpenIndiana-discuss mailing list
> OpenIndiana-discuss at openindiana.org
> http://openindiana.org/mailman/listinfo/openindiana-discuss
>


More information about the OpenIndiana-discuss mailing list