Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Feb 2024 18:14:34 +0000
From:      Shawn Webb <shawn.webb@hardenedbsd.org>
To:        Emmanuel Vadot <manu@freebsd.org>
Cc:        src-committers@freebsd.org, dev-commits-src-all@freebsd.org,  dev-commits-src-main@freebsd.org
Subject:   Re: git: 6e69612d5df1 - main - pam: Add pam_xdg module
Message-ID:  <2zwthawswhf5surxumjhhmvqpg6bauwl7ucog5kv3d33bej4ai@tpqxvtitsnt4>
In-Reply-To: <202402261735.41QHZvL1027958@gitrepo.freebsd.org>
References:  <202402261735.41QHZvL1027958@gitrepo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--b5b3qdh2angfxah3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Mon, Feb 26, 2024 at 05:35:57PM +0000, Emmanuel Vadot wrote:
> The branch main has been updated by manu:
>=20
> URL: https://cgit.FreeBSD.org/src/commit/?id=3D6e69612d5df1c1d5bd86990ea4=
d9a170c030b292
>=20
> commit 6e69612d5df1c1d5bd86990ea4d9a170c030b292
> Author:     Emmanuel Vadot <manu@FreeBSD.org>
> AuthorDate: 2024-02-21 14:51:05 +0000
> Commit:     Emmanuel Vadot <manu@FreeBSD.org>
> CommitDate: 2024-02-26 17:34:52 +0000
>=20
>     pam: Add pam_xdg module
>    =20
>     This is a module to setup the XDG directories and environment variabl=
es.
>     For now the only usage is to have a XDG_RUNTIME_DIR environment setup=
 at
>     user login.
>     All other environment variable have a default fallback so no need to =
export
>     them in this module.
>     The directory is created according to the XDG Base directory specific=
ation.
>    =20
>     The default base directory is /var/run/xdg/<username> but can be conf=
igured
>     using the runtime_dir=3D<dir> module option.
>    =20
>     According to the spec the directory *must* not survive a reboot so ad=
ding
>     var_run_enable=3D"YES" to rc.conf is highly recommanded.
>    =20
>     Reviewed by:    des, pauamma (manpages)
>     Differential Revision:  https://reviews.freebsd.org/D44011
>     Sponsored by:   Beckhoff Automation GmbH & Co. KG
> ---
>  lib/libpam/modules/modules.inc       |   1 +
>  lib/libpam/modules/pam_xdg/Makefile  |   6 +
>  lib/libpam/modules/pam_xdg/pam_xdg.8 |  56 +++++++
>  lib/libpam/modules/pam_xdg/pam_xdg.c | 311 +++++++++++++++++++++++++++++=
++++++
>  4 files changed, 374 insertions(+)

[snip]

> diff --git a/lib/libpam/modules/pam_xdg/pam_xdg.c b/lib/libpam/modules/pa=
m_xdg/pam_xdg.c
> new file mode 100644
> index 000000000000..40012fe463e0
> --- /dev/null
> +++ b/lib/libpam/modules/pam_xdg/pam_xdg.c
> @@ -0,0 +1,311 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2024 Beckhoff Automation GmbH & Co. KG
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distributio=
n.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PU=
RPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIAB=
LE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUE=
NTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOO=
DS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, S=
TRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY=
 WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/stat.h>
> +#include <dirent.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <pwd.h>
> +
> +#define	PAM_SM_SESSION
> +
> +#include <security/pam_appl.h>
> +#include <security/pam_modules.h>
> +#include <security/pam_mod_misc.h>
> +
> +#define	BASE_RUNTIME_DIR_PREFIX	"/var/run/xdg"
> +#define	RUNTIME_DIR_PREFIX	runtime_dir_prefix !=3D NULL ? runtime_dir_pr=
efix : BASE_RUNTIME_DIR_PREFIX
> +
> +#define	RUNTIME_DIR_PREFIX_MODE	0711
> +#define	RUNTIME_DIR_MODE	0700	/* XDG spec */
> +
> +#define	XDG_MAX_SESSION		100 /* Arbitrary limit because we need one */
> +
> +static int
> +_pam_xdg_open(pam_handle_t *pamh, int flags __unused,
> +    int argc __unused, const char *argv[] __unused)
> +{
> +	struct passwd *passwd;
> +	const char *user;
> +	const char *runtime_dir_prefix;
> +	struct stat sb;
> +	char *runtime_dir =3D NULL;
> +	char *xdg_session_file;
> +	int rv, rt_dir_prefix, rt_dir, session_file, i;
> +
> +	session_file =3D -1;
> +	rt_dir_prefix =3D -1;
> +	runtime_dir_prefix =3D openpam_get_option(pamh, "runtime_dir_prefix");
> +
> +	/* Get user info */
> +	rv =3D pam_get_item(pamh, PAM_USER, (const void **)&user);
> +	if (rv !=3D PAM_SUCCESS) {
> +		PAM_VERBOSE_ERROR("Can't get user information");
> +		goto out;
> +	}
> +	if ((passwd =3D getpwnam(user)) =3D=3D NULL) {
> +		PAM_VERBOSE_ERROR("Can't get user information");
> +		rv =3D PAM_SESSION_ERR;
> +		goto out;
> +	}
> +
> +	/* Open or create the base xdg directory */
> +	rt_dir_prefix =3D open(RUNTIME_DIR_PREFIX, O_DIRECTORY | O_NOFOLLOW);
> +	if (rt_dir_prefix < 0) {
> +		rt_dir_prefix =3D mkdir(RUNTIME_DIR_PREFIX, RUNTIME_DIR_PREFIX_MODE);
> +		if (rt_dir_prefix !=3D 0) {
> +			PAM_VERBOSE_ERROR("Can't mkdir %s", RUNTIME_DIR_PREFIX);
> +			rv =3D PAM_SESSION_ERR;
> +			goto out;
> +		}
> +		rt_dir_prefix =3D open(RUNTIME_DIR_PREFIX, O_DIRECTORY | O_NOFOLLOW);
> +	}
> +
> +	/* Open or create the user xdg directory */
> +	rt_dir =3D openat(rt_dir_prefix, user, O_DIRECTORY | O_NOFOLLOW);
> +	if (rt_dir < 0) {
> +		rt_dir =3D mkdirat(rt_dir_prefix, user, RUNTIME_DIR_MODE);
> +		if (rt_dir !=3D 0) {
> +			PAM_VERBOSE_ERROR("mkdir: %s/%s (%d)", RUNTIME_DIR_PREFIX, user, rt_d=
ir);
> +			rv =3D PAM_SESSION_ERR;
> +			goto out;
> +		}
> +		rv =3D fchownat(rt_dir_prefix, user, passwd->pw_uid, passwd->pw_gid, 0=
);
> +		if (rv !=3D 0) {
> +			PAM_VERBOSE_ERROR("fchownat: %s/%s (%d)", RUNTIME_DIR_PREFIX, user, r=
v);
> +			rv =3D unlinkat(rt_dir_prefix, user, AT_REMOVEDIR);
> +			if (rv =3D=3D -1)
> +				PAM_VERBOSE_ERROR("unlinkat: %s/%s (%d)", RUNTIME_DIR_PREFIX, user, =
errno);
> +			rv =3D PAM_SESSION_ERR;
> +			goto out;
> +		}
> +	} else {
> +		/* Check that the already create dir is correctly owned */
> +		rv =3D fstatat(rt_dir_prefix, user, &sb, 0);
> +		if (rv =3D=3D -1) {
> +			PAM_VERBOSE_ERROR("fstatat %s/%s failed (%d)", RUNTIME_DIR_PREFIX, us=
er, errno);
> +			rv =3D PAM_SESSION_ERR;
> +			goto out;
> +		}
> +		if (sb.st_uid !=3D passwd->pw_uid ||
> +		  sb.st_gid !=3D passwd->pw_gid) {
> +			PAM_VERBOSE_ERROR("%s/%s isn't owned by %d:%d\n", RUNTIME_DIR_PREFIX,=
 user, passwd->pw_uid, passwd->pw_gid);
> +			rv =3D PAM_SESSION_ERR;
> +			goto out;
> +		}
> +		/* Test directory mode */
> +		if ((sb.st_mode & 0x1FF) !=3D RUNTIME_DIR_MODE) {
> +			PAM_VERBOSE_ERROR("%s/%s have wrong mode\n", RUNTIME_DIR_PREFIX, user=
);
> +			rv =3D PAM_SESSION_ERR;
> +			goto out;
> +		}
> +	}
> +
> +	/* Setup the environment variable */
> +	asprintf(&runtime_dir, "XDG_RUNTIME_DIR=3D%s/%s", RUNTIME_DIR_PREFIX, u=
ser);
> +	rv =3D pam_putenv(pamh, runtime_dir);
> +	if (rv !=3D PAM_SUCCESS) {
> +		PAM_VERBOSE_ERROR("pam_putenv: failed (%d)", rv);
> +		rv =3D PAM_SESSION_ERR;
> +		goto out;
> +	}
> +
> +	/* Setup the session count file */
> +	for (i =3D 0; i < XDG_MAX_SESSION; i++) {
> +		asprintf(&xdg_session_file, "%s/xdg_session.%d", user, i);

If asprintf fails, xdg_session_file will be NULL.

> +		printf("Trying to open %s\n", xdg_session_file);
> +		session_file =3D openat(rt_dir_prefix, xdg_session_file, O_CREAT | O_E=
XCL, RUNTIME_DIR_MODE);

If xdg_session_file is NULL, there is a NULL pointer dereference
vulnerability in the above call to openat(2).

> +		free(xdg_session_file);
> +		if (session_file >=3D 0)
> +			break;

Thanks,

--=20
Shawn Webb
Cofounder / Security Engineer
HardenedBSD

Tor-ified Signal: +1 303-901-1600
https://git.hardenedbsd.org/hardenedbsd/pubkeys/-/raw/master/Shawn_Webb/03A=
4CBEBB82EA5A67D9F3853FF2E67A277F8E1FA.pub.asc

--b5b3qdh2angfxah3
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEA6TL67gupaZ9nzhT/y5nonf44foFAmXc1P0ACgkQ/y5nonf4
4fpsJA//dsUTrurhgPoofonbjZfhXiv1lXpdSToscxMogUEG1TAsGrMn+cvJPNne
0RUDc9FSuKz7mn/VCDxO9N1dEND9kbyZy2XEc0FJ64GFbM0Lr2eqKfO9Ez3lWI/l
P7bSfiD3NONgtlmHQDtYE4PmRi0q8kHq596OvQlOAuADHK2xT5BuOyqsLCZp1aPM
Db2zQxqt1+G6J46oOjGMWRaZH1l+ZCH4Q52cl9JDyZ0y7TlHyHCAsqm30e0C/7k+
u1UGBbwSeQYq4btlUBtjS7Yiivse+a65Dmdlz5GvKgf6fWgu144Py8GcV1ilACPQ
u0h20GJVsOKqiDdxVHZzZVCsnTyyMMo6ifW31WU9Ob0H14O2p3ftywYIdd8UOirV
EC1cuqmgtLcNwmGvn+wuRvmHteqzX+aoMnS/iRceuBK2Pt69AbMMgY1rLv0tQOwK
/9k/K8IRVDMU2c3bOZRd6TSpv1579O8uVZhn9agBlJ78nqnsOf9BbCb6yh9wG4Fj
cM0tk5KfHqrXWZdxHclg+LwA7aEsjuxsViI5KKPisIrhBIC5ZKu84f7Ki8qsvbt/
9fyKTPEctzO4cKNJoO/7XGnsWmw56a1ElLjVP0UTkuLBCc/T0C+CZNqLB7LjhFtf
4AjmqJRinqSLJxPQs1E/NMAERZVtu5X01TcDe3tV5mNGlR2Zto8=
=jG4B
-----END PGP SIGNATURE-----

--b5b3qdh2angfxah3--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2zwthawswhf5surxumjhhmvqpg6bauwl7ucog5kv3d33bej4ai>