diff options
author | 2019-08-03 15:22:17 +0000 | |
---|---|---|
committer | 2019-08-03 15:22:17 +0000 | |
commit | 044dcf883ed02b1363c7ba7b3bffa021c5f0e0e7 (patch) | |
tree | 684597aea2e891f092a5299b05573b368218f739 /sys/lib/libsa | |
parent | If the CPU frequency is available during TSC init, make it available (diff) | |
download | wireguard-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/Makefile | 5 | ||||
-rw-r--r-- | sys/lib/libsa/fchmod.c | 59 | ||||
-rw-r--r-- | sys/lib/libsa/stand.h | 3 | ||||
-rw-r--r-- | sys/lib/libsa/ufs.c | 57 | ||||
-rw-r--r-- | sys/lib/libsa/ufs.h | 3 | ||||
-rw-r--r-- | sys/lib/libsa/ufs2.c | 55 |
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) |