On Thu, 14 Apr 2022 17:52:37 -0500, joshua stein wrote:

> login_fbtab(3) supports wildcards but only for every file in a 
> directory (/path/*).
>
> This makes it use glob(3) so it can also support more specific 
> wildcards like /path/file*

Yes, it is better to use glob(3) than something custom.
Comments inline.

 - todd

> diff --git lib/libutil/login_fbtab.c lib/libutil/login_fbtab.c
> index 5eacf4f65ff..39621a0cde4 100644
> --- lib/libutil/login_fbtab.c
> +++ lib/libutil/login_fbtab.c
> @@ -61,8 +61,8 @@
>  #include <sys/stat.h>
>  
>  #include <errno.h>
> -#include <dirent.h>
>  #include <limits.h>
> +#include <glob.h>
>  #include <paths.h>
>  #include <stdio.h>
>  #include <stdlib.h>
> @@ -134,49 +134,32 @@ login_fbtab(const char *tty, uid_t uid, gid_t gid)
>  static void
>  login_protect(const char *path, mode_t mask, uid_t uid, gid_t gid)
>  {
> -     char    buf[PATH_MAX];
> -     size_t  pathlen = strlen(path);
> -     DIR     *dir;
> -     struct  dirent *ent;
> +     glob_t  g;
> +     size_t  n;
> +     char    *gpath;
>  
> -     if (pathlen >= sizeof(buf)) {
> +     if (strlen(path) > PATH_MAX) {

The test should be >= PATH_MAX since PATH_MAX includes space for
the NUL.

>               errno = ENAMETOOLONG;
>               syslog(LOG_ERR, "%s: %s: %m", _PATH_FBTAB, path);
>               return;
>       }
>  
> -     if (strcmp("/*", path + pathlen - 2) != 0) {
> -             if (chmod(path, mask) && errno != ENOENT)
> -                     syslog(LOG_ERR, "%s: chmod(%s): %m", _PATH_FBTAB, path)
> ;
> -             if (chown(path, uid, gid) && errno != ENOENT)
> -                     syslog(LOG_ERR, "%s: chown(%s): %m", _PATH_FBTAB, path)
> ;
> -     } else {
> -             /*
> -              * This is a wildcard directory (/path/to/whatever/ * ).
> -              * Make a copy of path without the trailing '*' (but leave
> -              * the trailing '/' so we can append directory entries.)
> -              */
> -             memcpy(buf, path, pathlen - 1);
> -             buf[pathlen - 1] = '\0';
> -             if ((dir = opendir(buf)) == NULL) {
> -                     syslog(LOG_ERR, "%s: opendir(%s): %m", _PATH_FBTAB,
> -                         path);
> -                     return;
> -             }
> +     g.gl_offs = 0;
> +     if (glob(path, GLOB_DOOFFS, NULL, &g) != 0) {

I don't think you need GLOB_DOOFFS and g.gl_offs here since you are
not reserving slots in gl_pathv.  I would just use GLOB_NOSORT
unless you need things to be sorted.

> +             if (errno != ENOENT)
> +                     syslog(LOG_ERR, "%s: glob(%s): %m", _PATH_FBTAB, path);
> +             globfree(&g);
> +             return;
> +     }
>  
> -             while ((ent = readdir(dir)) != NULL) {
> -                     if (strcmp(ent->d_name, ".")  != 0 &&
> -                         strcmp(ent->d_name, "..") != 0) {
> -                             buf[pathlen - 1] = '\0';
> -                             if (strlcat(buf, ent->d_name, sizeof(buf))
> -                                 >= sizeof(buf)) {
> -                                     errno = ENAMETOOLONG;
> -                                     syslog(LOG_ERR, "%s: %s: %m",
> -                                         _PATH_FBTAB, path);
> -                             } else
> -                                     login_protect(buf, mask, uid, gid);
> -                     }
> -             }
> -             closedir(dir);
> +     for (n = 0; n < g.gl_matchc; n++) {
> +             gpath = g.gl_pathv[n];
> +
> +             if (chmod(gpath, mask) && errno != ENOENT)
> +                     syslog(LOG_ERR, "%s: chmod(%s): %m", _PATH_FBTAB, gpath
> );
> +             if (chown(gpath, uid, gid) && errno != ENOENT)
> +                     syslog(LOG_ERR, "%s: chown(%s): %m", _PATH_FBTAB, gpath
> );
>       }
> +
> +     globfree(&g);
>  }

Reply via email to