summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/mksnap_ffs/mksnap_ffs.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/sbin/mksnap_ffs/mksnap_ffs.c b/sbin/mksnap_ffs/mksnap_ffs.c
index 58e73dc..13186b4 100644
--- a/sbin/mksnap_ffs/mksnap_ffs.c
+++ b/sbin/mksnap_ffs/mksnap_ffs.c
@@ -43,6 +43,7 @@
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -54,7 +55,7 @@ void usage(void);
int
main(int argc, char **argv)
{
- const char *dir;
+ char *dir, *cp, path[PATH_MAX];
struct ufs_args args;
struct group *grp;
struct stat stbuf;
@@ -66,6 +67,37 @@ main(int argc, char **argv)
dir = argv[1];
args.fspec = argv[2];
+ /*
+ * Check that the user running this program has permission
+ * to create and remove a snapshot file from the directory
+ * in which they have requested to have it made. If the
+ * directory is sticky and not owned by the user, then they
+ * will not be able to remove the snapshot when they are
+ * done with it.
+ */
+ if (strlen(args.fspec) >= PATH_MAX)
+ errx(1, "pathname too long %s", args.fspec);
+ cp = strrchr(args.fspec, '/');
+ if (cp == NULL) {
+ strlcpy(path, ".", PATH_MAX);
+ } else if (cp == args.fspec) {
+ strlcpy(path, "/", PATH_MAX);
+ } else {
+ strlcpy(path, args.fspec, cp - args.fspec + 1);
+ }
+ if (stat(path, &stbuf) < 0)
+ err(1, "%s", path);
+ if (!S_ISDIR(stbuf.st_mode))
+ errx(1, "%s: Not a directory", path);
+ if (access(path, W_OK) < 0)
+ err(1, "Lack write permission in %s", path);
+ if ((stbuf.st_mode & S_ISTXT) && stbuf.st_uid != getuid())
+ errx(1, "Lack write permission in %s: Sticky bit set", path);
+
+ /*
+ * Having verified access to the directory in which the
+ * snapshot is to be built, proceed with creating it.
+ */
if ((grp = getgrnam("operator")) == NULL)
errx(1, "Cannot retrieve operator gid");
if (mount("ffs", dir, MNT_UPDATE | MNT_SNAPSHOT, &args) < 0)
OpenPOWER on IntegriCloud