Bug 9558 - Change notification broken for non-root users with vfs_notify_fam and gamin
Change notification broken for non-root users with vfs_notify_fam and gamin
Status: RESOLVED WONTFIX
Product: Samba 3.6
Classification: Unclassified
Component: VFS Modules
3.6.10
x64 FreeBSD
: P5 minor
: ---
Assigned To: Samba Bugzilla Account
Samba QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2013-01-12 04:00 UTC by Danny Warren
Modified: 2013-02-17 04:26 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Danny Warren 2013-01-12 04:00:14 UTC
PLATFORM:

FreeBSD: 9.1-RELEASE amd64
Samba: 3.6.9 (Applicable to newer versions as well)
Gamin: 0.1.10 (Applicable to newer versions as well)


EXPECTED:

When using gamin, the vfs_notify_fam module should create a fam socket in the context of the current user (/tmp/fam-$USER/fam-SAMBA).

Basically, fam sockets with gamin should work for all connecting users.


ACTUAL:

When using gamin, the vfs_notify_fam module only ever creates a socket for root (/tmp/fam-root/fam-SAMBA) that is inaccessible to non-root users.

Basically, fam breaks with gamin for all non-root connecting users.


ERRORS:

The following errors are thrown by gamin when connecting as a non-root user and show up in the samba logs:

  Socket directory /tmp/fam-root has different owner
  Failed to remove unsafe path /tmp/fam-root

However, if you change a share to "force user = root" and browse that share, there are no errors and change notifications seems to work.


DETAIL:

If you start an instance of gam_server as root before starting samba, you can watch the fam socket:

  /usr/local/libexec/gam_server --notimeout SAMBA

When doing this, you will see no attempts to talk to the socket from non-root users as gamin blocks communication with it before it even reaches that point.

When browsing a "force user = root" share, however, the gam_server instance spits out logs confirming it will only talk to root.


BACKGROUND:

The way gamin handles security is documented here:

  http://people.gnome.org/~veillard/gamin/security.html

In short, it always creates sockets on a per-user basis, owned by that user and with 0700 permissions.  No other user can talk to it.

If another user tries, gamin stops it and spits out the error seen above.

It looks like gamin enforces this by determining the username of the user that invoked the api call, as seen in "libgamin/gam_api.c":

  /**
  * gamin_get_user_name:
  *
  * Get the user name for the current process.
  *
  * Returns a new string or NULL in case of error.
  */
  static const char *
  gamin_get_user_name(void)
  {
    struct passwd *pw;

    if (user_name[0] != 0)
    return (user_name);

    pw = getpwuid(getuid());

    if (pw != NULL) {
    strncpy(user_name, pw->pw_name, 99);
    user_name[99] = 0;
    }

    return(user_name);
  }

There does not seem to be any way to tell gamin to create the socket on behalf of a user when running as root.  You have to *BE* that user or gamin's is not going to play along.


FIX:

To make gamin work, you will need to drop to the unprivileged connecting user before calling "FAMOpen2".  

Unfortunately this hits my limit of knowledge about how the vfs modules work under samba, so I can't figure out if that is doable.  Otherwise I'd provide a patch.

Any ideas?  Thanks!
Comment 1 Volker Lendecke 2013-01-12 16:26:42 UTC
This sounds like a gamin deficiency. getuid() is not a good indication of Samba's user id. We change our euid, not the uid, because we have to get back to root eventually. Not sure how to fix this.

You're on FreeBSD? Maybe a direct kevent vfs module to receive notifies would help?
Comment 2 Danny Warren 2013-01-12 22:02:11 UTC
That makes complete sense, thanks for taking a look at all this.

Agreed that it's a gamin deficiency.

However, I doubt that it will get corrected in gamin any time soon as the project seems basically dead.  There hasn't been a release since 2008, patches submitted via bugzilla/git seem to go ignored, and the author hasn't responded on their mailing list in years.

After your explanation made the uid/euid thing click for me, I found this patch in their bugzilla repo:

https://bugzilla.gnome.org/show_bug.cgi?id=345244

...which looks to already cover exactly what would need done to get gamin to respect the effective uid for samba.  But it was never applied nor did gamin's author respond to it.

So looks like I have a few options here.  See if that simple patch does the trick and attempt to get it applied to the freebsd port (and make sure other gamin-dependent apps haven't hacked around this).  Or try and wake up gamin's author to do a release.  Or write a new kqueue or inotify based vfs module for samba.

Either way it's good that there is something googlable out there about this issue.  I found lots of threads with people scratching their heads on this one with no research being done as to why.

Marking this resolved as the issue isn't on samba's side.  If I make headway on one of the above I'll come back and note it here.
Comment 3 Timur Bakeyev 2013-01-31 21:17:35 UTC
Danny, we have power to patch our ports despite outdated upstream software. I'd recommend you to file a PR and CC me with this patch.

Volker, can you go into a bit more details regarding kevent support? How would you  inject that into VFS code?

I have a tvent module with kevent support, but dunno, how that can be enforced in S36 and cooperate with VFS in particular.
Comment 4 Danny Warren 2013-01-31 21:48:32 UTC
(In reply to comment #3)
> Danny, we have power to patch our ports despite outdated upstream software. I'd
> recommend you to file a PR and CC me with this patch.
> 
> Volker, can you go into a bit more details regarding kevent support? How would
> you  inject that into VFS code?
> 
> I have a tvent module with kevent support, but dunno, how that can be enforced
> in S36 and cooperate with VFS in particular.

Timur, I already have a patch in the works that adds a RUN_AS_EFFECTIVE_USER config option to the gamin port. :)

Once that is in place, I assume you can flip that bit in gamin when compiling it as a dependency of samba?

Unfortunately I got slammed at my day job, so I haven't had time to polish it up and push it to GNATS.

It mostly worked, but I bumped in to some odd behavior that needed more research, and want to be extra careful since it's something that involves setuid (I put extra checks in place to prevent elevation to root, etc).

All of the fixes are on the gamin side, samba looks to be doing everything correctly here.

Scrapping gamin and instead hacking on a proper freebsd VFS module is probably worthwhile as well.
Comment 5 Timur Bakeyev 2013-02-01 02:12:03 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > Danny, we have power to patch our ports despite outdated upstream software. I'd
> > recommend you to file a PR and CC me with this patch.
> > 
> > Volker, can you go into a bit more details regarding kevent support? How would
> > you  inject that into VFS code?
> > 
> > I have a tvent module with kevent support, but dunno, how that can be enforced
> > in S36 and cooperate with VFS in particular.
> 
> Timur, I already have a patch in the works that adds a RUN_AS_EFFECTIVE_USER
> config option to the gamin port. :)

I don't think we need a special switch for it - just add this functionality.

> Unfortunately I got slammed at my day job, so I haven't had time to polish it
> up and push it to GNATS.
> 
> It mostly worked, but I bumped in to some odd behavior that needed more
> research, and want to be extra careful since it's something that involves
> setuid (I put extra checks in place to prevent elevation to root, etc).

Take your time - we all doing it in our free time, unfortunately...

> Scrapping gamin and instead hacking on a proper freebsd VFS module is probably
> worthwhile as well.

That would be ideal case, but real solution is to fix kqueue to act as inotify in Linux. Right now it's merely a hack, that enforced to open thousands of files, as kqueue works only with FDs :(
Comment 6 Volker Lendecke 2013-02-01 09:36:11 UTC
(In reply to comment #3) 
> Volker, can you go into a bit more details regarding kevent support? How would
> you  inject that into VFS code?
> 
> I have a tvent module with kevent support, but dunno, how that can be enforced
> in S36 and cooperate with VFS in particular.

My idea was to look at how gamin retrieves its information from the kernel. I had thought that there was kevent support for something similar to inotify. This could be plugged directly into a VFS module.

For kevent support in tevent: I don't know if we would put this into 3.6 proper. If you don't want to wait for master Samba to trickle into a release, you could propose the kevent backend for master, and we could make a lightweight tevent release. 3.6 should be able to work with a current external tevent library. If it does not, that's a bug that we will fix.
Comment 7 Danny Warren 2013-02-17 04:26:18 UTC
Phew, I finally got some time this weekend to pick this up again.

I've finalized the patch and submitted it via GNATS:

http://www.freebsd.org/cgi/query-pr.cgi?pr=176203

Timur, once gamin's port maintainer decides how they want to handle it, I will let you know if you need to tweak samba's makefile in any way.  If they decide to keep the drop privileges patch optional, you might have to check whether that option has been set and throw a warning if not.

The file alteration monitor stuff is working great on my home network right now! :)