mounts to polydirs not working

Bug #1908638 reported by Evan Linde
12
This bug affects 1 person
Affects Status Importance Assigned to Milestone
libpam-mount (Debian)
Fix Released
Unknown
libpam-mount (Ubuntu)
Fix Released
Low
Unassigned
Focal
New
Low
Unassigned
Jammy
New
Low
Unassigned
Kinetic
Fix Released
Low
Unassigned

Bug Description

Using a polyinstantiated directory as a mount point is not working in focal (20.04.1) with libpam-mount 2.16-10.

The problem is only when the polydir itself is used as a mountpoint; there is no problem using a subdirectory inside the polydir. (e.g. If "/data2" is defined as a polydir in /etc/security/pam_namespace.conf, pam_mount succeeds when using /data2/subdir as a mount point, but fails when using /data2 as the mount point.)

I think the problem is this patch: 0014-Don-t-compare-source-when-checking-if-it-s-already-m.patch

Expected behavior: A filesystem should be mounted at the polydir or at least debug logs should show an attempted mount command.

Observed behavior: Nothing is mounted and the following lines are logged by both systemd and login (debugging enabled in pam_mount.conf.xml)

(mount.c:250): Mount info: globalconf, user=elinde <volume fstype="cifs" server="stor1" path="data" mountpoint="/data2" cipher="(null)" fskeypath="(null)" fskeycipher="(null)" fskeyhash="(null)" options="multiuser,cruid=elinde,sec=krb5,cifsacl" /> fstab=0 ssh=0

(mount.c:622): data already seems to be mounted at /data2, skipping

The behavior I'm looking for does work in bionic (18.04.5) with libpam-mount 2.16-3ubuntu0.1.

Tags: focal
Evan Linde (elinde)
description: updated
Evan Linde (elinde)
tags: added: focal
Revision history for this message
Jochen Sprickerhof (v-launchpad-jochen-sprickerhof-de) wrote :

Hi Evan,

thanks for opening the bug, it is indeed a result of the 0014-Don-t-compare-source-when-checking-if-it-s-already-m.patch.
As far as I understand polydirs are implemented as mount overlays and so /data2 in your example is a mount point already.
You can test this with this example using the same functions as libpam-mount:

// sudo apt install gcc libmount-dev; cc -o lsmount lsmount.c -lmount; ./lsmount

#include <libmount/libmount.h>

int main()
{
 struct libmnt_context *ctx;
 struct libmnt_table *table;
 struct libmnt_iter *iter;
 struct libmnt_fs *fs;

 ctx = mnt_new_context();
 if (ctx == NULL)
  return -1;
 if (mnt_context_get_mtab(ctx, &table) != 0)
  goto out;
 iter = mnt_new_iter(MNT_ITER_BACKWARD);
 if (iter == NULL)
  goto out;

 while (mnt_table_next_fs(table, iter, &fs) == 0)
     printf("source:\t%s target: %s\n", mnt_fs_get_source(fs), mnt_fs_get_target(fs));
 out:
 mnt_free_context(ctx);
 return 0;
}

It should list /data2 as a target if run as the user with the polydir.
As far as I understand, mounting something on top of the polydir would hide the polydir.

Can you give some more background of your setup?

Revision history for this message
Evan Linde (elinde) wrote :

Hi Jochen,

Thank you for taking a look at this. My setup is for a lab that uses a central storage server to host all their data (homes, shared dirs, everything) so that workstations are fully interchangeable. The storage server is accessible via cifs using campus AD credentials. The storage volume containing the lab's data is shared at the root level and mounted at a specific top-level directory (e.g. "/data2") on the lab's workstations and some hosted systems in the HPC center; user homes look like "/data2/home/{username}".

I have found that file ownership and permissions aren't set properly for users on the cifs share if they use a mount made by another user. (I don't have notes on everything I tried, but I spent a while a couple years ago testing various mount options without finding anything satisfactory.) I have used polydirs to get around this problem; by making the mount point (/data2) a polydir, each user is able to mount the cifs share to the same mount point using their own credentials even if another user is already logged in and has the share mounted.

Here's what I see for the polydir using the code you provided:

source: /dev/mapper/ubuntu--vg-ubuntu--lv target: /data2

Revision history for this message
Jochen Sprickerhof (v-launchpad-jochen-sprickerhof-de) wrote :
Revision history for this message
Evan Linde (elinde) wrote :

That would work OK for home directories but not for everything else. There are several shared directories in the volume; they are expected to be at paths like "/data2/share1", etc, so they wouldn't be able to use a parameterized mount like the home directories. This still leaves us with ownership and permission problems (on the shared directories) in the case where a second user logs into the same system where someone else is already logged in.

On a related note, the polydirs also helpful for getting around cases where pam_mount fails to unmount a volume. It may only be because one user's polydir is invisible to other users, but I suspect that the namespace teardown is actually more reliable.

Revision history for this message
Jochen Sprickerhof (v-launchpad-jochen-sprickerhof-de) wrote :

The behavior prior to the 14* patch was to only mount if (path, mountpoint) are not listed as mounted. But some mount helpers rewrite the path before mounting (like cryptsetup transitioning through /dev/mapper or NFS, as detailed in https://bugs.debian.org/799752). For those the check always fails and the mount would be redone on every login. The patch drops the path from the check as it is not predictable and only checks if mountpoint is listed as mounted.

Your use case is the other way round, you want to mount something on top of a mount point. The only way I see this works is by adding an option to not check for mounts at all. Maybe checkmounted?

Revision history for this message
Evan Linde (elinde) wrote :

Is "checkmounted" a standard / API function somewhere?

As mentioned earlier, my use case does work prior to the 14* patch since both path and mountpoint need to match an existing mount (rather than only the mountpoint) for pam_mount to decide something is already mounted.

I'm not seeing how the path gets to be unpredictable (at least for NFS on the linked bug). It looks more like vpt->volume might be failing to match the source path in pmt_utabent_matches as a result of certain xml configs because it's using the content of the path element verbatim instead of constructing it from multiple elements (e.g. 'path="nfs:/home/prisoners/p"' vs. 'server="nfs" path="/home/prisoners/p"') as happens in pmt_vol_to_dev.

Revision history for this message
Jochen Sprickerhof (v-launchpad-jochen-sprickerhof-de) wrote :

> Is "checkmounted" a standard / API function somewhere?

No, that would be a new option to be added.

> I'm not seeing how the path gets to be unpredictable (at least for NFS on the linked bug). It looks more like vpt->volume might be failing to match the source path in pmt_utabent_matches as a result of certain xml configs because it's using the content of the path element verbatim instead of constructing it from multiple elements (e.g. 'path="nfs:/home/prisoners/p"' vs. 'server="nfs" path="/home/prisoners/p"') as happens in pmt_vol_to_dev.

Interesting, I was not aware of this function. Still there could be other functions applied. for example I have path="/dev/disk/by-label/home" which is passed to mount.crypt and transformed to /dev/mapper/_dev_nvme0n1p3 in the mount output. This is done in dmc_crypto_name but it could be a function outside of pam_mount as well.

Revision history for this message
Evan Linde (elinde) wrote :

>> Is "checkmounted" a standard / API function somewhere?

> No, that would be a new option to be added.

Are you thinking of an xml config option? e.g.:

<volume ... checkmounted="1" ... />

If so, another option like "ignoresource" might be useful. I'm thinking something like:

checkmounted="0/1/true/false"
    When 1/true: don't make mount attempt if volume is already mounted
    When 0/false: attempt mount without checking if already mounted
    Default: 1/true
ignoresource="0/1/true/false"
    (Only evaluated when checkmounted=1/true)
    When 1/true: only require mountpoint to be already used
    When 0/false: require both mountpoint and source to match
    Default: 0/false

>> I'm not seeing how the path gets to be unpredictable (at least for NFS on the linked bug). It looks more like vpt->volume might be failing to match the source path in pmt_utabent_matches as a result of certain xml configs because it's using the content of the path element verbatim instead of constructing it from multiple elements (e.g. 'path="nfs:/home/prisoners/p"' vs. 'server="nfs" path="/home/prisoners/p"') as happens in pmt_vol_to_dev.

> Interesting, I was not aware of this function. Still there could be other functions applied. for example I have path="/dev/disk/by-label/home" which is passed to mount.crypt and transformed to /dev/mapper/_dev_nvme0n1p3 in the mount output. This is done in dmc_crypto_name but it could be a function outside of pam_mount as well.

After more looking around, it looks like pam_utabent_matches really ought to be using vpt->combopath instead of vpt->volume since it is being set reliably in mount_op and defaults to being a copy of vpt->volume. I have submitted a merge request with pam_mount upstream for this.

Revision history for this message
Jochen Sprickerhof (v-launchpad-jochen-sprickerhof-de) wrote :

> If so, another option like "ignoresource" might be useful. I'm thinking
> something like:
>
> checkmounted="0/1/true/false"
> ignoresource="0/1/true/false"

Yes, I think both would make sense.

> After more looking around, it looks like pam_utabent_matches really ought to be using vpt->combopath instead of vpt->volume since it is being set reliably in mount_op and defaults to being a copy of vpt->volume. I have submitted a merge request with pam_mount upstream for this.

That probably solves it for NFS but still not for mount.crypt. We could add a
case CMD_CRYPTMOUNT in there and compute the path as mount.crypt does but
would need an extra variable as it's not the same as vpt->combopath.

Revision history for this message
Paride Legovini (paride) wrote :

Hello Evan and thanks for this bug report. IIUC your upstream MP is [1]. Would it be possible for you to also file an upstream bug report and to link it to this Ubuntu bug? This would make progress tracking easier.

I'm triaging this with Importance: Low due to the uncommon configuration where the issue happens. Given that libpam-mount is currently a sync from Debian I think that best way to fix this is also the most "natural" one: Upstream -> Debian -> Ubuntu.

[1] https://sourceforge.net/p/pam-mount/pam-mount/merge-requests/3/

Changed in libpam-mount (Ubuntu):
status: New → Triaged
importance: Undecided → Low
Revision history for this message
Evan Linde (elinde) wrote :

This bug report is now also submitted to Debian:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=980117

Changed in libpam-mount (Debian):
status: Unknown → New
Revision history for this message
Oliver Ford (ojford) wrote :

I have a similar issue using a FUSE mount (gocryptfs) - however it is not resolved by @elinde's patch, though I'm grateful for the pointer in the right direction.

In my case the volume `path` mounted is `/usr/bin/gocryptfs#/home/%(USER).cipher` in `pam_mount.conf.xml`, and this corresponds to both `vpt->combopath` *and* `vpt->volume`, since:

```
// pam_mount.h excerpt

/**
 * @server: server name, if any
 * @volume: path relative to server, or full path in case @server is empty
 * @combopath: concatenation of @server and @volume dependent upon @fstype
 */
struct vol {
```

in my case `server` is null. I'm not sure what the right fix is here, check if `combopath` begins with `server` (if not null) and ends with `"#" + volume` if `fstype = "fuse"`, perhaps?

Changed in libpam-mount (Debian):
status: New → Fix Released
Revision history for this message
Bryce Harrington (bryce) wrote :

This issue is documented as fixed in Debian's 2.19-1 release, which has sync'd into Ubuntu:

 libpam-mount | 2.18-2build2 | jammy
 libpam-mount | 2.19-1 | kinetic
libpam-mount | 2.19-1 | unstable

It sounds like the issue was a regression since Debian's 2.16-4 release, according to the Debian bug report; this suggests the issue affects Focal and Jammy but not Bionic. I've opened bug tasks for those releases and am marking Kinetic fixed, but keeping importance as Low for now, per comment #10, and as such this might not be viable for SRU. However, if it would be SRU'd, the fix in question would be this one:

https://salsa.debian.org/debian/libpam-mount/-/commit/7cf094a705da9f24ffb09fccde06889433451ded

Changed in libpam-mount (Ubuntu Kinetic):
status: Triaged → Fix Released
Changed in libpam-mount (Ubuntu Focal):
importance: Undecided → Low
Changed in libpam-mount (Ubuntu Jammy):
importance: Undecided → Low
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.