summaryrefslogtreecommitdiffstats
path: root/sys/lib/libsa
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2019-08-03 15:22:17 +0000
committerderaadt <deraadt@openbsd.org>2019-08-03 15:22:17 +0000
commit044dcf883ed02b1363c7ba7b3bffa021c5f0e0e7 (patch)
tree684597aea2e891f092a5299b05573b368218f739 /sys/lib/libsa
parentIf the CPU frequency is available during TSC init, make it available (diff)
downloadwireguard-openbsd-044dcf883ed02b1363c7ba7b3bffa021c5f0e0e7.tar.xz
wireguard-openbsd-044dcf883ed02b1363c7ba7b3bffa021c5f0e0e7.zip
In the bootblocks, after discovering and opening /bsd.upgrade, fchmod -x
so the file cannot be re-executed upon the next boot. This provides a stronger one-shot-upgrade model than the upgrade script's rm /bsd.upgrade. Now various forms of upgrade failure will reboot into /bsd, which is probably more recoverable. Performing fchmod -x depends on (1) use of MI boot.c (not alpha/macppc/sparc64/sgi/octeon) and (2) "can write blocks" functionality in the IO layer. Most architectures have this support now. Two diagnostics "fchmod a-x %s: failed" and "/bsd.upgrade is not u+x" will remain in the tree while refinements happen for some of the laggard architectures. based upon a discussion florian tested in snapshots for more than a week without any complaints
Diffstat (limited to 'sys/lib/libsa')
-rw-r--r--sys/lib/libsa/Makefile5
-rw-r--r--sys/lib/libsa/fchmod.c59
-rw-r--r--sys/lib/libsa/stand.h3
-rw-r--r--sys/lib/libsa/ufs.c57
-rw-r--r--sys/lib/libsa/ufs.h3
-rw-r--r--sys/lib/libsa/ufs2.c55
6 files changed, 176 insertions, 6 deletions
diff --git a/sys/lib/libsa/Makefile b/sys/lib/libsa/Makefile
index a4b9fdcf26b..8cac7712bbb 100644
--- a/sys/lib/libsa/Makefile
+++ b/sys/lib/libsa/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.29 2019/04/20 22:59:04 deraadt Exp $
+# $OpenBSD: Makefile,v 1.30 2019/08/03 15:22:17 deraadt Exp $
# $NetBSD: Makefile,v 1.13 1996/10/02 16:19:51 ws Exp $
LIB= sa
@@ -34,7 +34,8 @@ SRCS+= divdi3.c qdivrem.c
# io routines
SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c cons.c ioctl.c \
- lseek.c open.c nullfs.c read.c stat.c fstat.c write.c readdir.c
+ lseek.c open.c nullfs.c read.c stat.c fchmod.c fstat.c \
+ write.c readdir.c
# boot filesystems
SRCS+= ufs.c cd9660.c
diff --git a/sys/lib/libsa/fchmod.c b/sys/lib/libsa/fchmod.c
new file mode 100644
index 00000000000..7d9bc9cac36
--- /dev/null
+++ b/sys/lib/libsa/fchmod.c
@@ -0,0 +1,59 @@
+/* $OpenBSD: fchmod.c,v 1.1 2019/08/03 15:22:17 deraadt Exp $ */
+/* $NetBSD: stat.c,v 1.3 1994/10/26 05:45:07 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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 distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ * @(#)stat.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include "stand.h"
+
+int
+fchmod(int fd, mode_t m)
+{
+ struct open_file *f = &files[fd];
+
+ if (f->f_ops->fchmod == NULL) {
+ errno = EOPNOTSUPP;
+ return (-1);
+ }
+ if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) {
+ errno = EBADF;
+ return (-1);
+ }
+
+ /* operation not defined on raw devices */
+ if (f->f_flags & F_RAW) {
+ errno = EOPNOTSUPP;
+ return (-1);
+ }
+
+ errno = (f->f_ops->fchmod)(f, m);
+ return (0);
+}
diff --git a/sys/lib/libsa/stand.h b/sys/lib/libsa/stand.h
index 5e78f153770..d4b56fd1331 100644
--- a/sys/lib/libsa/stand.h
+++ b/sys/lib/libsa/stand.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: stand.h,v 1.66 2019/04/20 22:59:04 deraadt Exp $ */
+/* $OpenBSD: stand.h,v 1.67 2019/08/03 15:22:17 deraadt Exp $ */
/* $NetBSD: stand.h,v 1.18 1996/11/30 04:35:51 gwr Exp $ */
/*-
@@ -67,6 +67,7 @@ struct fs_ops {
off_t (*seek)(struct open_file *f, off_t offset, int where);
int (*stat)(struct open_file *f, struct stat *sb);
int (*readdir)(struct open_file *f, char *);
+ int (*fchmod)(struct open_file *f, mode_t);
};
extern struct fs_ops file_system[];
diff --git a/sys/lib/libsa/ufs.c b/sys/lib/libsa/ufs.c
index e768beaef24..9ba26a49048 100644
--- a/sys/lib/libsa/ufs.c
+++ b/sys/lib/libsa/ufs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufs.c,v 1.26 2016/11/25 17:00:33 reyk Exp $ */
+/* $OpenBSD: ufs.c,v 1.27 2019/08/03 15:22:17 deraadt Exp $ */
/* $NetBSD: ufs.c,v 1.16 1996/09/30 16:01:22 ws Exp $ */
/*-
@@ -81,6 +81,7 @@ struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
struct ufs1_dinode f_di; /* copy of on-disk inode */
+ ufsino_t f_ino; /* our inode number */
int f_nindir[NIADDR];
/* number of blocks mapped by
indirect block at level i */
@@ -95,6 +96,7 @@ struct file {
};
static int read_inode(ufsino_t, struct open_file *);
+static int chmod_inode(ufsino_t, struct open_file *, mode_t);
static int block_map(struct open_file *, daddr32_t, daddr32_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int search_directory(char *, struct open_file *, ufsino_t *);
@@ -154,6 +156,50 @@ out:
}
/*
+ * Read a new inode into a file structure.
+ */
+static int
+chmod_inode(ufsino_t inumber, struct open_file *f, mode_t mode)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct fs *fs = fp->f_fs;
+ char *buf;
+ size_t rsize;
+ int rc;
+
+ /*
+ * Read inode and save it.
+ */
+ buf = alloc(fs->fs_bsize);
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
+ buf, &rsize);
+ if (rc)
+ goto out;
+ if (rsize != (size_t)fs->fs_bsize) {
+ rc = EIO;
+ goto out;
+ }
+
+ {
+ struct ufs1_dinode *dp;
+
+ dp = &((struct ufs1_dinode *)buf)[ino_to_fsbo(fs, inumber)];
+ dp->di_mode = mode;
+ }
+
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
+ fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
+ buf, NULL);
+
+out:
+ free(buf, fs->fs_bsize);
+ return (rc);
+}
+
+/*
* Given an offset in a file, find the disk block number that
* contains that block.
*/
@@ -522,6 +568,7 @@ ufs_open(char *path, struct open_file *f)
/*
* Found terminal component.
*/
+ fp->f_ino = inumber;
rc = 0;
out:
if (buf)
@@ -639,6 +686,14 @@ ufs_stat(struct open_file *f, struct stat *sb)
return (0);
}
+int
+ufs_fchmod(struct open_file *f, mode_t mode)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ return chmod_inode(fp->f_ino, f, mode);
+}
+
#ifndef NO_READDIR
int
ufs_readdir(struct open_file *f, char *name)
diff --git a/sys/lib/libsa/ufs.h b/sys/lib/libsa/ufs.h
index 3f68af48d24..42122d1448c 100644
--- a/sys/lib/libsa/ufs.h
+++ b/sys/lib/libsa/ufs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufs.h,v 1.6 2003/06/02 23:28:10 millert Exp $ */
+/* $OpenBSD: ufs.h,v 1.7 2019/08/03 15:22:17 deraadt Exp $ */
/* $NetBSD: ufs.h,v 1.5 1995/10/20 01:35:25 cgd Exp $ */
/*-
@@ -41,4 +41,5 @@ int ufs_write(struct open_file *f, void *buf,
off_t ufs_seek(struct open_file *f, off_t offset, int where);
int ufs_stat(struct open_file *f, struct stat *sb);
int ufs_readdir(struct open_file *f, char *name);
+int ufs_fchmod(struct open_file *f, mode_t mode);
diff --git a/sys/lib/libsa/ufs2.c b/sys/lib/libsa/ufs2.c
index b4b68c8eb0c..f36d2d155d2 100644
--- a/sys/lib/libsa/ufs2.c
+++ b/sys/lib/libsa/ufs2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufs2.c,v 1.7 2016/11/27 13:57:32 reyk Exp $ */
+/* $OpenBSD: ufs2.c,v 1.8 2019/08/03 15:22:17 deraadt Exp $ */
/*-
* Copyright (c) 1993
@@ -80,6 +80,7 @@ struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
struct ufs2_dinode f_di; /* copy of on-disk inode */
+ ufsino_t f_ino; /* our inode number */
int f_nindir[NIADDR];
/* number of blocks mapped by
indirect block at level i */
@@ -94,6 +95,7 @@ struct file {
};
static int read_inode(ufsino_t, struct open_file *);
+static int chmod_inode(ufsino_t, struct open_file *, mode_t);
static int block_map(struct open_file *, daddr_t, daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int search_directory(char *, struct open_file *, ufsino_t *);
@@ -152,6 +154,48 @@ out:
}
/*
+ * Read a new inode into a file structure.
+ */
+static int
+chmod_inode(ufsino_t inumber, struct open_file *f, mode_t mode)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ struct fs *fs = fp->f_fs;
+ char *buf;
+ size_t rsize;
+ int rc;
+
+ /*
+ * Read inode and save it.
+ */
+ buf = alloc(fs->fs_bsize);
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, buf, &rsize);
+ if (rc)
+ goto out;
+ if (rsize != (size_t)fs->fs_bsize) {
+ rc = EIO;
+ goto out;
+ }
+
+ {
+ struct ufs2_dinode *dp;
+
+ dp = &((struct ufs2_dinode *)buf)[ino_to_fsbo(fs, inumber)];
+ dp->di_mode = mode;
+ }
+
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
+ fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize, buf, NULL);
+
+out:
+ free(buf, fs->fs_bsize);
+ return (rc);
+}
+
+/*
* Given an offset in a file, find the disk block number that
* contains that block.
*/
@@ -520,6 +564,7 @@ ufs2_open(char *path, struct open_file *f)
/*
* Found terminal component.
*/
+ fp->f_ino = inumber;
rc = 0;
out:
if (buf)
@@ -637,6 +682,14 @@ ufs2_stat(struct open_file *f, struct stat *sb)
return (0);
}
+int
+ufs2_fchmod(struct open_file *f, mode_t mode)
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ return chmod_inode(fp->f_ino, f, mode);
+}
+
#ifndef NO_READDIR
int
ufs2_readdir(struct open_file *f, char *name)