svn commit: r344861 - in stable/11: sbin/fsck_ffs sbin/fsdb sys/ufs/ffs
Shawn Webb
shawn.webb at hardenedbsd.org
Fri Mar 8 02:33:26 UTC 2019
On Wed, Mar 06, 2019 at 11:59:56PM +0000, Kirk McKusick wrote:
> Author: mckusick
> Date: Wed Mar 6 23:59:56 2019
> New Revision: 344861
> URL: https://svnweb.freebsd.org/changeset/base/344861
>
> Log:
> MFC of 344552 and 344732
>
> Have fsck_ffs adjust size for files with hole at end
>
> Tighten last lbn calculation
>
> Sponsored by: Netflix
>
> Modified:
> stable/11/sbin/fsck_ffs/fsck.h
> stable/11/sbin/fsck_ffs/globs.c
> stable/11/sbin/fsck_ffs/inode.c
> stable/11/sbin/fsck_ffs/pass1.c
> stable/11/sbin/fsck_ffs/setup.c
> stable/11/sbin/fsdb/fsdb.c
> stable/11/sys/ufs/ffs/ffs_alloc.c
> stable/11/sys/ufs/ffs/fs.h
> Directory Properties:
> stable/11/ (props changed)
>
> Modified: stable/11/sbin/fsck_ffs/fsck.h
> ==============================================================================
> --- stable/11/sbin/fsck_ffs/fsck.h Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sbin/fsck_ffs/fsck.h Wed Mar 6 23:59:56 2019 (r344861)
> @@ -230,6 +230,7 @@ struct inodesc {
> ufs_lbn_t id_lbn; /* logical block number of current block */
> ufs2_daddr_t id_blkno; /* current block number being examined */
> int id_numfrags; /* number of frags contained in block */
> + ufs_lbn_t id_lballoc; /* pass1: last LBN that is allocated */
> off_t id_filesize; /* for DATA nodes, the size of the directory */
> ufs2_daddr_t id_entryno;/* for DATA nodes, current entry number */
> int id_loc; /* for DATA nodes, current location in dir */
> @@ -289,6 +290,7 @@ extern long countdirs; /* number of directories we ac
> #define MIBSIZE 3 /* size of fsck sysctl MIBs */
> extern int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */
> extern int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */
> +extern int setsize[MIBSIZE]; /* MIB command to set inode size */
> extern int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */
> extern int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */
> extern int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */
>
> Modified: stable/11/sbin/fsck_ffs/globs.c
> ==============================================================================
> --- stable/11/sbin/fsck_ffs/globs.c Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sbin/fsck_ffs/globs.c Wed Mar 6 23:59:56 2019 (r344861)
> @@ -61,6 +61,7 @@ unsigned long numdirs, listmax;
> long countdirs; /* number of directories we actually found */
> int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */
> int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */
> +int setsize[MIBSIZE]; /* MIB command to set inode size */
> int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */
> int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */
> int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */
> @@ -128,6 +129,7 @@ fsckinit(void)
> countdirs = 0;
> bzero(adjrefcnt, sizeof(int) * MIBSIZE);
> bzero(adjblkcnt, sizeof(int) * MIBSIZE);
> + bzero(setsize, sizeof(int) * MIBSIZE);
> bzero(adjndir, sizeof(int) * MIBSIZE);
> bzero(adjnbfree, sizeof(int) * MIBSIZE);
> bzero(adjnifree, sizeof(int) * MIBSIZE);
>
> Modified: stable/11/sbin/fsck_ffs/inode.c
> ==============================================================================
> --- stable/11/sbin/fsck_ffs/inode.c Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sbin/fsck_ffs/inode.c Wed Mar 6 23:59:56 2019 (r344861)
> @@ -124,9 +124,9 @@ ckinode(union dinode *dp, struct inodesc *idesc)
> ret = iblock(idesc, i + 1, remsize, BT_LEVEL1 + i);
> if (ret & STOP)
> return (ret);
> - } else {
> + } else if (remsize > 0) {
> idesc->id_lbn += sizepb / sblock.fs_bsize;
> - if (idesc->id_type == DATA && remsize > 0) {
> + if (idesc->id_type == DATA) {
> /* An empty block in a directory XXX */
> getpathname(pathbuf, idesc->id_number,
> idesc->id_number);
>
> Modified: stable/11/sbin/fsck_ffs/pass1.c
> ==============================================================================
> --- stable/11/sbin/fsck_ffs/pass1.c Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sbin/fsck_ffs/pass1.c Wed Mar 6 23:59:56 2019 (r344861)
> @@ -245,6 +245,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int r
> off_t kernmaxfilesize;
> ufs2_daddr_t ndb;
> mode_t mode;
> + uintmax_t fixsize;
> int j, ret, offset;
>
> if ((dp = getnextinode(inumber, rebuildcg)) == NULL)
> @@ -375,6 +376,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int r
> idesc->id_type = SNAP;
> else
> idesc->id_type = ADDR;
> + idesc->id_lballoc = -1;
> (void)ckinode(dp, idesc);
> if (sblock.fs_magic == FS_UFS2_MAGIC && dp->dp2.di_extsize > 0) {
> idesc->id_type = ADDR;
> @@ -420,6 +422,46 @@ checkinode(ino_t inumber, struct inodesc *idesc, int r
> rwerror("ADJUST INODE BLOCK COUNT", cmd.value);
> }
> }
> + /*
> + * Soft updates will always ensure that the file size is correct
> + * for files that contain only direct block pointers. However
> + * soft updates does not roll back sizes for files with indirect
> + * blocks that it has set to unallocated because their contents
> + * have not yet been written to disk. Hence, the file can appear
> + * to have a hole at its end because the block pointer has been
> + * rolled back to zero. Thus, id_lballoc tracks the last allocated
> + * block in the file. Here, for files that extend into indirect
> + * blocks, we check for a size past the last allocated block of
> + * the file and if that is found, shorten the file to reference
> + * the last allocated block to avoid having it reference a hole
> + * at its end.
> + */
> + if (DIP(dp, di_size) > UFS_NDADDR * sblock.fs_bsize &&
> + idesc->id_lballoc < lblkno(&sblock, DIP(dp, di_size) - 1)) {
> + fixsize = lblktosize(&sblock, idesc->id_lballoc + 1);
> + pwarn("INODE %lu: FILE SIZE %ju BEYOND END OF ALLOCATED FILE, "
> + "SIZE SHOULD BE %ju", (u_long)inumber,
> + (uintmax_t)DIP(dp, di_size), fixsize);
> + if (preen)
> + printf(" (ADJUSTED)\n");
> + else if (reply("ADJUST") == 0)
> + return (1);
> + if (bkgrdflag == 0) {
> + dp = ginode(inumber);
> + DIP_SET(dp, di_size, fixsize);
> + inodirty(dp);
> + } else {
> + cmd.value = idesc->id_number;
> + cmd.size = fixsize;
> + if (debug)
> + printf("setsize ino %ju size set to %ju\n",
> + (uintmax_t)cmd.value, (uintmax_t)cmd.size);
> + if (sysctl(setsize, MIBSIZE, 0, 0,
> + &cmd, sizeof cmd) == -1)
> + rwerror("SET INODE SIZE", cmd.value);
> + }
> +
> + }
> return (1);
> unknown:
> pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber);
> @@ -521,5 +563,7 @@ pass1check(struct inodesc *idesc)
> */
> idesc->id_entryno++;
> }
> + if (idesc->id_lballoc == -1 || idesc->id_lballoc < idesc->id_lbn)
> + idesc->id_lballoc = idesc->id_lbn;
> return (res);
> }
>
> Modified: stable/11/sbin/fsck_ffs/setup.c
> ==============================================================================
> --- stable/11/sbin/fsck_ffs/setup.c Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sbin/fsck_ffs/setup.c Wed Mar 6 23:59:56 2019 (r344861)
> @@ -134,6 +134,7 @@ setup(char *dev)
> size = MIBSIZE;
> if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0||
> sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0||
> + sysctlnametomib("vfs.ffs.setsize", setsize, &size) < 0 ||
> sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0||
> sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 ||
> sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) {
>
> Modified: stable/11/sbin/fsdb/fsdb.c
> ==============================================================================
> --- stable/11/sbin/fsdb/fsdb.c Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sbin/fsdb/fsdb.c Wed Mar 6 23:59:56 2019 (r344861)
> @@ -157,6 +157,7 @@ CMDFUNC(chctime); /* Change ctime */
> CMDFUNC(chatime); /* Change atime */
> CMDFUNC(chinum); /* Change inode # of dirent */
> CMDFUNC(chname); /* Change dirname of dirent */
> +CMDFUNC(chsize); /* Change size */
>
> struct cmdtable cmds[] = {
> { "help", "Print out help", 1, 1, FL_RO, helpfn },
> @@ -186,6 +187,7 @@ struct cmdtable cmds[] = {
> { "chgrp", "Change group of current inode to GROUP", 2, 2, FL_WR, chgroup },
> { "chflags", "Change flags of current inode to FLAGS", 2, 2, FL_WR, chaflags },
> { "chgen", "Change generation number of current inode to GEN", 2, 2, FL_WR, chgen },
> + { "chsize", "Change size of current inode to SIZE", 2, 2, FL_WR, chsize },
> { "btime", "Change btime of current inode to BTIME", 2, 2, FL_WR, chbtime },
> { "mtime", "Change mtime of current inode to MTIME", 2, 2, FL_WR, chmtime },
> { "ctime", "Change ctime of current inode to CTIME", 2, 2, FL_WR, chctime },
> @@ -1009,6 +1011,31 @@ CMDFUNCSTART(chgen)
> }
> DIP_SET(curinode, di_gen, gen);
> inodirty();
> + printactive(0);
> + return rval;
> +}
> +
> +CMDFUNCSTART(chsize)
> +{
> + int rval = 1;
> + off_t size;
> + char *cp;
> +
> + if (!checkactive())
> + return 1;
> +
> + size = strtoll(argv[1], &cp, 0);
> + if (cp == argv[1] || *cp != '\0') {
> + warnx("bad size `%s'", argv[1]);
> + return 1;
> + }
> +
> + if (size < 0) {
> + warnx("size set to negative (%jd)\n", (intmax_t)size);
> + return(1);
> + }
> + DIP_SET(curinode, di_size, size);
> + inodirty(curinode);
> printactive(0);
> return rval;
> }
>
> Modified: stable/11/sys/ufs/ffs/ffs_alloc.c
> ==============================================================================
> --- stable/11/sys/ufs/ffs/ffs_alloc.c Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sys/ufs/ffs/ffs_alloc.c Wed Mar 6 23:59:56 2019 (r344861)
> @@ -2688,6 +2688,8 @@ ffs_fserr(fs, inum, cp)
> * the count to zero will cause the inode to be freed.
> * adjblkcnt(inode, amt) - adjust the number of blocks used by the
> * inode by the specified amount.
> + * adjsize(inode, size) - set the size of the inode to the
> + * specified size.
> * adjndir, adjbfree, adjifree, adjffree, adjnumclusters(amt) -
> * adjust the superblock summary.
> * freedirs(inode, count) - directory inodes [inode..inode + count - 1]
> @@ -2729,6 +2731,9 @@ SYSCTL_PROC(_vfs_ffs, FFS_ADJ_REFCNT, adjrefcnt, CTLFL
> static SYSCTL_NODE(_vfs_ffs, FFS_ADJ_BLKCNT, adjblkcnt, CTLFLAG_WR,
> sysctl_ffs_fsck, "Adjust Inode Used Blocks Count");
>
> +static SYSCTL_NODE(_vfs_ffs, FFS_SET_SIZE, setsize, CTLFLAG_WR,
> + sysctl_ffs_fsck, "Set the inode size");
> +
> static SYSCTL_NODE(_vfs_ffs, FFS_ADJ_NDIR, adjndir, CTLFLAG_WR,
> sysctl_ffs_fsck, "Adjust number of directories");
>
> @@ -2875,6 +2880,23 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
> break;
> ip = VTOI(vp);
> DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + cmd.size);
> + ip->i_flag |= IN_CHANGE | IN_MODIFIED;
> + error = ffs_update(vp, 1);
> + vput(vp);
> + break;
> +
> + case FFS_SET_SIZE:
> +#ifdef DEBUG
> + if (fsckcmds) {
> + printf("%s: set inode %jd size to %jd\n",
> + mp->mnt_stat.f_mntonname, (intmax_t)cmd.value,
> + (intmax_t)cmd.size);
> + }
> +#endif /* DEBUG */
> + if ((error = ffs_vget(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
> + break;
> + ip = VTOI(vp);
> + DIP_SET(ip, i_size, cmd.size);
> ip->i_flag |= IN_CHANGE | IN_MODIFIED;
> error = ffs_update(vp, 1);
> vput(vp);
>
> Modified: stable/11/sys/ufs/ffs/fs.h
> ==============================================================================
> --- stable/11/sys/ufs/ffs/fs.h Wed Mar 6 23:54:55 2019 (r344860)
> +++ stable/11/sys/ufs/ffs/fs.h Wed Mar 6 23:59:56 2019 (r344861)
> @@ -219,7 +219,8 @@
> #define FFS_UNLINK 14 /* remove a name in the filesystem */
> #define FFS_SET_INODE 15 /* update an on-disk inode */
> #define FFS_SET_BUFOUTPUT 16 /* set buffered writing on descriptor */
> -#define FFS_MAXID 16 /* number of valid ffs ids */
> +#define FFS_SET_SIZE 17 /* set inode size */
> +#define FFS_MAXID 17 /* number of valid ffs ids */
Hey Kirk,
This MFC breaks buildworld:
http://jenkins.hardenedbsd.org/jenkins/job/HardenedBSD-11-STABLE-amd64/904/console
I'll take a look at providing a patch to fix it soon, unless you're
able to get to it before I am.
Thanks,
--
Shawn Webb
Cofounder and Security Engineer
HardenedBSD
Tor-ified Signal: +1 443-546-8752
Tor+XMPP+OTR: lattera at is.a.hacker.sx
GPG Key ID: 0x6A84658F52456EEE
GPG Key Fingerprint: 2ABA B6BD EF6A F486 BE89 3D9E 6A84 658F 5245 6EEE
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/svn-src-all/attachments/20190307/4ee588f4/attachment.sig>
More information about the svn-src-all
mailing list