Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull misc vfs updates from Al Viro:
"Assorted stuff all over the place (the largest group here is
Christoph's stat cleanups)"

* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
fs: remove KSTAT_QUERY_FLAGS
fs: remove vfs_stat_set_lookup_flags
fs: move vfs_fstatat out of line
fs: implement vfs_stat and vfs_lstat in terms of vfs_fstatat
fs: remove vfs_statx_fd
fs: omfs: use kmemdup() rather than kmalloc+memcpy
[PATCH] reduce boilerplate in fsid handling
fs: Remove duplicated flag O_NDELAY occurring twice in VALID_OPEN_FLAGS
selftests: mount: add nosymfollow tests
Add a "nosymfollow" mount option.

+308 -129
+1 -2
fs/9p/vfs_super.c
··· 260 260 buf->f_bavail = rs.bavail; 261 261 buf->f_files = rs.files; 262 262 buf->f_ffree = rs.ffree; 263 - buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; 264 - buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; 263 + buf->f_fsid = u64_to_fsid(rs.fsid); 265 264 buf->f_namelen = rs.namelen; 266 265 } 267 266 if (res != -ENOSYS)
+1 -2
fs/adfs/super.c
··· 210 210 buf->f_namelen = sbi->s_namelen; 211 211 buf->f_bsize = sb->s_blocksize; 212 212 buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks; 213 - buf->f_fsid.val[0] = (u32)id; 214 - buf->f_fsid.val[1] = (u32)(id >> 32); 213 + buf->f_fsid = u64_to_fsid(id); 215 214 216 215 return 0; 217 216 }
+1 -2
fs/affs/super.c
··· 620 620 buf->f_blocks = AFFS_SB(sb)->s_partition_size - AFFS_SB(sb)->s_reserved; 621 621 buf->f_bfree = free; 622 622 buf->f_bavail = free; 623 - buf->f_fsid.val[0] = (u32)id; 624 - buf->f_fsid.val[1] = (u32)(id >> 32); 623 + buf->f_fsid = u64_to_fsid(id); 625 624 buf->f_namelen = AFFSNAMEMAX; 626 625 return 0; 627 626 }
+1 -2
fs/befs/linuxvfs.c
··· 963 963 buf->f_bavail = buf->f_bfree; 964 964 buf->f_files = 0; /* UNKNOWN */ 965 965 buf->f_ffree = 0; /* UNKNOWN */ 966 - buf->f_fsid.val[0] = (u32)id; 967 - buf->f_fsid.val[1] = (u32)(id >> 32); 966 + buf->f_fsid = u64_to_fsid(id); 968 967 buf->f_namelen = BEFS_NAME_LEN; 969 968 970 969 befs_debug(sb, "<--- %s", __func__);
+1 -2
fs/bfs/inode.c
··· 229 229 buf->f_bfree = buf->f_bavail = info->si_freeb; 230 230 buf->f_files = info->si_lasti + 1 - BFS_ROOT_INO; 231 231 buf->f_ffree = info->si_freei; 232 - buf->f_fsid.val[0] = (u32)id; 233 - buf->f_fsid.val[1] = (u32)(id >> 32); 232 + buf->f_fsid = u64_to_fsid(id); 234 233 buf->f_namelen = BFS_NAMELEN; 235 234 return 0; 236 235 }
+1 -2
fs/ceph/super.c
··· 104 104 le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1)); 105 105 mutex_unlock(&monc->mutex); 106 106 107 - buf->f_fsid.val[0] = fsid & 0xffffffff; 108 - buf->f_fsid.val[1] = fsid >> 32; 107 + buf->f_fsid = u64_to_fsid(fsid); 109 108 110 109 return 0; 111 110 }
+1 -2
fs/cramfs/inode.c
··· 690 690 buf->f_bavail = 0; 691 691 buf->f_files = CRAMFS_SB(sb)->files; 692 692 buf->f_ffree = 0; 693 - buf->f_fsid.val[0] = (u32)id; 694 - buf->f_fsid.val[1] = (u32)(id >> 32); 693 + buf->f_fsid = u64_to_fsid(id); 695 694 buf->f_namelen = CRAMFS_MAXPATHLEN; 696 695 return 0; 697 696 }
+1 -2
fs/efs/super.c
··· 342 342 sbi->inode_blocks * 343 343 (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); 344 344 buf->f_ffree = sbi->inode_free; /* free inodes */ 345 - buf->f_fsid.val[0] = (u32)id; 346 - buf->f_fsid.val[1] = (u32)(id >> 32); 345 + buf->f_fsid = u64_to_fsid(id); 347 346 buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */ 348 347 349 348 return 0;
+1 -2
fs/erofs/super.c
··· 561 561 562 562 buf->f_namelen = EROFS_NAME_LEN; 563 563 564 - buf->f_fsid.val[0] = (u32)id; 565 - buf->f_fsid.val[1] = (u32)(id >> 32); 564 + buf->f_fsid = u64_to_fsid(id); 566 565 return 0; 567 566 } 568 567
+1 -2
fs/exfat/super.c
··· 89 89 buf->f_blocks = sbi->num_clusters - 2; /* clu 0 & 1 */ 90 90 buf->f_bfree = buf->f_blocks - sbi->used_clusters; 91 91 buf->f_bavail = buf->f_bfree; 92 - buf->f_fsid.val[0] = (unsigned int)id; 93 - buf->f_fsid.val[1] = (unsigned int)(id >> 32); 92 + buf->f_fsid = u64_to_fsid(id); 94 93 /* Unicode utf16 255 characters */ 95 94 buf->f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE; 96 95 return 0;
+1 -2
fs/ext2/super.c
··· 1455 1455 buf->f_namelen = EXT2_NAME_LEN; 1456 1456 fsid = le64_to_cpup((void *)es->s_uuid) ^ 1457 1457 le64_to_cpup((void *)es->s_uuid + sizeof(u64)); 1458 - buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; 1459 - buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; 1458 + buf->f_fsid = u64_to_fsid(fsid); 1460 1459 spin_unlock(&sbi->s_lock); 1461 1460 return 0; 1462 1461 }
+1 -2
fs/ext4/super.c
··· 6144 6144 buf->f_namelen = EXT4_NAME_LEN; 6145 6145 fsid = le64_to_cpup((void *)es->s_uuid) ^ 6146 6146 le64_to_cpup((void *)es->s_uuid + sizeof(u64)); 6147 - buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; 6148 - buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; 6147 + buf->f_fsid = u64_to_fsid(fsid); 6149 6148 6150 6149 #ifdef CONFIG_QUOTA 6151 6150 if (ext4_test_inode_flag(dentry->d_inode, EXT4_INODE_PROJINHERIT) &&
+1 -2
fs/f2fs/super.c
··· 1442 1442 } 1443 1443 1444 1444 buf->f_namelen = F2FS_NAME_LEN; 1445 - buf->f_fsid.val[0] = (u32)id; 1446 - buf->f_fsid.val[1] = (u32)(id >> 32); 1445 + buf->f_fsid = u64_to_fsid(id); 1447 1446 1448 1447 #ifdef CONFIG_QUOTA 1449 1448 if (is_inode_flag_set(dentry->d_inode, FI_PROJ_INHERIT) &&
+1 -2
fs/fat/inode.c
··· 836 836 buf->f_blocks = sbi->max_cluster - FAT_START_ENT; 837 837 buf->f_bfree = sbi->free_clusters; 838 838 buf->f_bavail = sbi->free_clusters; 839 - buf->f_fsid.val[0] = (u32)id; 840 - buf->f_fsid.val[1] = (u32)(id >> 32); 839 + buf->f_fsid = u64_to_fsid(id); 841 840 buf->f_namelen = 842 841 (sbi->options.isvfat ? FAT_LFN_LEN : 12) * NLS_MAX_CHARSET_SIZE; 843 842
+1 -2
fs/hfs/super.c
··· 104 104 buf->f_bavail = buf->f_bfree; 105 105 buf->f_files = HFS_SB(sb)->fs_ablocks; 106 106 buf->f_ffree = HFS_SB(sb)->free_ablocks; 107 - buf->f_fsid.val[0] = (u32)id; 108 - buf->f_fsid.val[1] = (u32)(id >> 32); 107 + buf->f_fsid = u64_to_fsid(id); 109 108 buf->f_namelen = HFS_NAMELEN; 110 109 111 110 return 0;
+1 -2
fs/hfsplus/super.c
··· 320 320 buf->f_bavail = buf->f_bfree; 321 321 buf->f_files = 0xFFFFFFFF; 322 322 buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid; 323 - buf->f_fsid.val[0] = (u32)id; 324 - buf->f_fsid.val[1] = (u32)(id >> 32); 323 + buf->f_fsid = u64_to_fsid(id); 325 324 buf->f_namelen = HFSPLUS_MAX_STRLEN; 326 325 327 326 return 0;
+1 -2
fs/hpfs/super.c
··· 192 192 buf->f_bavail = sbi->sb_n_free; 193 193 buf->f_files = sbi->sb_dirband_size / 4; 194 194 buf->f_ffree = hpfs_get_free_dnodes(s); 195 - buf->f_fsid.val[0] = (u32)id; 196 - buf->f_fsid.val[1] = (u32)(id >> 32); 195 + buf->f_fsid = u64_to_fsid(id); 197 196 buf->f_namelen = 254; 198 197 199 198 hpfs_unlock(s);
+1 -2
fs/isofs/inode.c
··· 1038 1038 buf->f_bavail = 0; 1039 1039 buf->f_files = ISOFS_SB(sb)->s_ninodes; 1040 1040 buf->f_ffree = 0; 1041 - buf->f_fsid.val[0] = (u32)id; 1042 - buf->f_fsid.val[1] = (u32)(id >> 32); 1041 + buf->f_fsid = u64_to_fsid(id); 1043 1042 buf->f_namelen = NAME_MAX; 1044 1043 return 0; 1045 1044 }
+1 -2
fs/minix/inode.c
··· 383 383 buf->f_files = sbi->s_ninodes; 384 384 buf->f_ffree = minix_count_free_inodes(sb); 385 385 buf->f_namelen = sbi->s_namelen; 386 - buf->f_fsid.val[0] = (u32)id; 387 - buf->f_fsid.val[1] = (u32)(id >> 32); 386 + buf->f_fsid = u64_to_fsid(id); 388 387 389 388 return 0; 390 389 }
+2 -1
fs/namei.c
··· 1626 1626 return ERR_PTR(error); 1627 1627 } 1628 1628 1629 - if (unlikely(nd->flags & LOOKUP_NO_SYMLINKS)) 1629 + if (unlikely(nd->flags & LOOKUP_NO_SYMLINKS) || 1630 + unlikely(link->mnt->mnt_flags & MNT_NOSYMFOLLOW)) 1630 1631 return ERR_PTR(-ELOOP); 1631 1632 1632 1633 if (!(nd->flags & LOOKUP_RCU)) {
+2
fs/namespace.c
··· 3171 3171 mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); 3172 3172 if (flags & MS_RDONLY) 3173 3173 mnt_flags |= MNT_READONLY; 3174 + if (flags & MS_NOSYMFOLLOW) 3175 + mnt_flags |= MNT_NOSYMFOLLOW; 3174 3176 3175 3177 /* The default atime for remount is preservation */ 3176 3178 if ((flags & MS_REMOUNT) &&
+1 -2
fs/nilfs2/super.c
··· 651 651 buf->f_files = nmaxinodes; 652 652 buf->f_ffree = nfreeinodes; 653 653 buf->f_namelen = NILFS_NAME_LEN; 654 - buf->f_fsid.val[0] = (u32)id; 655 - buf->f_fsid.val[1] = (u32)(id >> 32); 654 + buf->f_fsid = u64_to_fsid(id); 656 655 657 656 return 0; 658 657 }
+1 -2
fs/ntfs/super.c
··· 2643 2643 * the least significant 32-bits in f_fsid[0] and the most significant 2644 2644 * 32-bits in f_fsid[1]. 2645 2645 */ 2646 - sfs->f_fsid.val[0] = vol->serial_no & 0xffffffff; 2647 - sfs->f_fsid.val[1] = (vol->serial_no >> 32) & 0xffffffff; 2646 + sfs->f_fsid = u64_to_fsid(vol->serial_no); 2648 2647 /* Maximum length of filenames. */ 2649 2648 sfs->f_namelen = NTFS_MAX_NAME_LEN; 2650 2649 return 0;
+2 -4
fs/omfs/inode.c
··· 282 282 buf->f_blocks = sbi->s_num_blocks; 283 283 buf->f_files = sbi->s_num_blocks; 284 284 buf->f_namelen = OMFS_NAMELEN; 285 - buf->f_fsid.val[0] = (u32)id; 286 - buf->f_fsid.val[1] = (u32)(id >> 32); 285 + buf->f_fsid = u64_to_fsid(id); 287 286 288 287 buf->f_bfree = buf->f_bavail = buf->f_ffree = 289 288 omfs_count_free(s); ··· 362 363 bh = sb_bread(sb, block++); 363 364 if (!bh) 364 365 goto nomem_free; 365 - *ptr = kmalloc(sb->s_blocksize, GFP_KERNEL); 366 + *ptr = kmemdup(bh->b_data, sb->s_blocksize, GFP_KERNEL); 366 367 if (!*ptr) { 367 368 brelse(bh); 368 369 goto nomem_free; 369 370 } 370 - memcpy(*ptr, bh->b_data, sb->s_blocksize); 371 371 if (count < sb->s_blocksize) 372 372 memset((void *)*ptr + count, 0xff, 373 373 sb->s_blocksize - count);
+1
fs/proc_namespace.c
··· 70 70 { MNT_NOATIME, ",noatime" }, 71 71 { MNT_NODIRATIME, ",nodiratime" }, 72 72 { MNT_RELATIME, ",relatime" }, 73 + { MNT_NOSYMFOLLOW, ",nosymfollow" }, 73 74 { 0, NULL } 74 75 }; 75 76 const struct proc_fs_opts *fs_infop;
+1 -2
fs/qnx4/inode.c
··· 137 137 buf->f_bfree = qnx4_count_free_blocks(sb); 138 138 buf->f_bavail = buf->f_bfree; 139 139 buf->f_namelen = QNX4_NAME_MAX; 140 - buf->f_fsid.val[0] = (u32)id; 141 - buf->f_fsid.val[1] = (u32)(id >> 32); 140 + buf->f_fsid = u64_to_fsid(id); 142 141 143 142 return 0; 144 143 }
+1 -2
fs/qnx6/inode.c
··· 166 166 buf->f_ffree = fs32_to_cpu(sbi, sbi->sb->sb_free_inodes); 167 167 buf->f_bavail = buf->f_bfree; 168 168 buf->f_namelen = QNX6_LONG_NAME_MAX; 169 - buf->f_fsid.val[0] = (u32)id; 170 - buf->f_fsid.val[1] = (u32)(id >> 32); 169 + buf->f_fsid = u64_to_fsid(id); 171 170 172 171 return 0; 173 172 }
+1 -2
fs/romfs/super.c
··· 416 416 buf->f_bfree = buf->f_bavail = buf->f_ffree; 417 417 buf->f_blocks = 418 418 (romfs_maxsize(dentry->d_sb) + ROMBSIZE - 1) >> ROMBSBITS; 419 - buf->f_fsid.val[0] = (u32)id; 420 - buf->f_fsid.val[1] = (u32)(id >> 32); 419 + buf->f_fsid = u64_to_fsid(id); 421 420 return 0; 422 421 } 423 422
+1 -2
fs/squashfs/super.c
··· 380 380 buf->f_files = msblk->inodes; 381 381 buf->f_ffree = 0; 382 382 buf->f_namelen = SQUASHFS_NAME_LEN; 383 - buf->f_fsid.val[0] = (u32)id; 384 - buf->f_fsid.val[1] = (u32)(id >> 32); 383 + buf->f_fsid = u64_to_fsid(id); 385 384 386 385 return 0; 387 386 }
+29 -41
fs/stat.c
··· 56 56 * @path: file to get attributes from 57 57 * @stat: structure to return attributes in 58 58 * @request_mask: STATX_xxx flags indicating what the caller wants 59 - * @query_flags: Query mode (KSTAT_QUERY_FLAGS) 59 + * @query_flags: Query mode (AT_STATX_SYNC_TYPE) 60 60 * 61 61 * Get attributes without calling security_inode_getattr. 62 62 * ··· 71 71 72 72 memset(stat, 0, sizeof(*stat)); 73 73 stat->result_mask |= STATX_BASIC_STATS; 74 - query_flags &= KSTAT_QUERY_FLAGS; 74 + query_flags &= AT_STATX_SYNC_TYPE; 75 75 76 76 /* allow the fs to override these if it really wants to */ 77 77 /* SB_NOATIME means filesystem supplies dummy atime value */ ··· 97 97 * @path: The file of interest 98 98 * @stat: Where to return the statistics 99 99 * @request_mask: STATX_xxx flags indicating what the caller wants 100 - * @query_flags: Query mode (KSTAT_QUERY_FLAGS) 100 + * @query_flags: Query mode (AT_STATX_SYNC_TYPE) 101 101 * 102 102 * Ask the filesystem for a file's attributes. The caller must indicate in 103 103 * request_mask and query_flags to indicate what they want. ··· 126 126 EXPORT_SYMBOL(vfs_getattr); 127 127 128 128 /** 129 - * vfs_statx_fd - Get the enhanced basic attributes by file descriptor 129 + * vfs_fstat - Get the basic attributes by file descriptor 130 130 * @fd: The file descriptor referring to the file of interest 131 131 * @stat: The result structure to fill in. 132 - * @request_mask: STATX_xxx flags indicating what the caller wants 133 - * @query_flags: Query mode (KSTAT_QUERY_FLAGS) 134 132 * 135 133 * This function is a wrapper around vfs_getattr(). The main difference is 136 134 * that it uses a file descriptor to determine the file location. 137 135 * 138 136 * 0 will be returned on success, and a -ve error code if unsuccessful. 139 137 */ 140 - int vfs_statx_fd(unsigned int fd, struct kstat *stat, 141 - u32 request_mask, unsigned int query_flags) 138 + int vfs_fstat(int fd, struct kstat *stat) 142 139 { 143 140 struct fd f; 144 - int error = -EBADF; 145 - 146 - if (query_flags & ~KSTAT_QUERY_FLAGS) 147 - return -EINVAL; 141 + int error; 148 142 149 143 f = fdget_raw(fd); 150 - if (f.file) { 151 - error = vfs_getattr(&f.file->f_path, stat, 152 - request_mask, query_flags); 153 - fdput(f); 154 - } 144 + if (!f.file) 145 + return -EBADF; 146 + error = vfs_getattr(&f.file->f_path, stat, STATX_BASIC_STATS, 0); 147 + fdput(f); 155 148 return error; 156 - } 157 - EXPORT_SYMBOL(vfs_statx_fd); 158 - 159 - static inline unsigned vfs_stat_set_lookup_flags(unsigned *lookup_flags, 160 - int flags) 161 - { 162 - if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | 163 - AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0) 164 - return -EINVAL; 165 - 166 - *lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT; 167 - if (flags & AT_SYMLINK_NOFOLLOW) 168 - *lookup_flags &= ~LOOKUP_FOLLOW; 169 - if (flags & AT_NO_AUTOMOUNT) 170 - *lookup_flags &= ~LOOKUP_AUTOMOUNT; 171 - if (flags & AT_EMPTY_PATH) 172 - *lookup_flags |= LOOKUP_EMPTY; 173 - 174 - return 0; 175 149 } 176 150 177 151 /** ··· 163 189 * 164 190 * 0 will be returned on success, and a -ve error code if unsuccessful. 165 191 */ 166 - int vfs_statx(int dfd, const char __user *filename, int flags, 192 + static int vfs_statx(int dfd, const char __user *filename, int flags, 167 193 struct kstat *stat, u32 request_mask) 168 194 { 169 195 struct path path; 170 - int error = -EINVAL; 171 - unsigned lookup_flags; 196 + unsigned lookup_flags = 0; 197 + int error; 172 198 173 - if (vfs_stat_set_lookup_flags(&lookup_flags, flags)) 199 + if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH | 200 + AT_STATX_SYNC_TYPE)) 174 201 return -EINVAL; 202 + 203 + if (!(flags & AT_SYMLINK_NOFOLLOW)) 204 + lookup_flags |= LOOKUP_FOLLOW; 205 + if (!(flags & AT_NO_AUTOMOUNT)) 206 + lookup_flags |= LOOKUP_AUTOMOUNT; 207 + if (flags & AT_EMPTY_PATH) 208 + lookup_flags |= LOOKUP_EMPTY; 209 + 175 210 retry: 176 211 error = user_path_at(dfd, filename, lookup_flags, &path); 177 212 if (error) ··· 200 217 out: 201 218 return error; 202 219 } 203 - EXPORT_SYMBOL(vfs_statx); 204 220 221 + int vfs_fstatat(int dfd, const char __user *filename, 222 + struct kstat *stat, int flags) 223 + { 224 + return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, 225 + stat, STATX_BASIC_STATS); 226 + } 205 227 206 228 #ifdef __ARCH_WANT_OLD_STAT 207 229
+2
fs/statfs.c
··· 29 29 flags |= ST_NODIRATIME; 30 30 if (mnt_flags & MNT_RELATIME) 31 31 flags |= ST_RELATIME; 32 + if (mnt_flags & MNT_NOSYMFOLLOW) 33 + flags |= ST_NOSYMFOLLOW; 32 34 return flags; 33 35 } 34 36
+1 -2
fs/sysv/inode.c
··· 98 98 buf->f_files = sbi->s_ninodes; 99 99 buf->f_ffree = sysv_count_free_inodes(sb); 100 100 buf->f_namelen = SYSV_NAMELEN; 101 - buf->f_fsid.val[0] = (u32)id; 102 - buf->f_fsid.val[1] = (u32)(id >> 32); 101 + buf->f_fsid = u64_to_fsid(id); 103 102 return 0; 104 103 } 105 104
+1 -2
fs/udf/super.c
··· 2414 2414 + buf->f_bfree; 2415 2415 buf->f_ffree = buf->f_bfree; 2416 2416 buf->f_namelen = UDF_NAME_LEN; 2417 - buf->f_fsid.val[0] = (u32)id; 2418 - buf->f_fsid.val[1] = (u32)(id >> 32); 2417 + buf->f_fsid = u64_to_fsid(id); 2419 2418 2420 2419 return 0; 2421 2420 }
+1 -2
fs/ufs/super.c
··· 1431 1431 ? (buf->f_bfree - uspi->s_root_blocks) : 0; 1432 1432 buf->f_files = uspi->s_ncg * uspi->s_ipg; 1433 1433 buf->f_namelen = UFS_MAXNAMLEN; 1434 - buf->f_fsid.val[0] = (u32)id; 1435 - buf->f_fsid.val[1] = (u32)(id >> 32); 1434 + buf->f_fsid = u64_to_fsid(id); 1436 1435 1437 1436 mutex_unlock(&UFS_SB(sb)->s_lock); 1438 1437
+1 -2
fs/xfs/xfs_super.c
··· 794 794 statp->f_namelen = MAXNAMELEN - 1; 795 795 796 796 id = huge_encode_dev(mp->m_ddev_targp->bt_dev); 797 - statp->f_fsid.val[0] = (u32)id; 798 - statp->f_fsid.val[1] = (u32)(id >> 32); 797 + statp->f_fsid = u64_to_fsid(id); 799 798 800 799 icount = percpu_counter_sum(&mp->m_icount); 801 800 ifree = percpu_counter_sum(&mp->m_ifree);
+1 -2
fs/zonefs/super.c
··· 1116 1116 1117 1117 fsid = le64_to_cpup((void *)sbi->s_uuid.b) ^ 1118 1118 le64_to_cpup((void *)sbi->s_uuid.b + sizeof(u64)); 1119 - buf->f_fsid.val[0] = (u32)fsid; 1120 - buf->f_fsid.val[1] = (u32)(fsid >> 32); 1119 + buf->f_fsid = u64_to_fsid(fsid); 1121 1120 1122 1121 return 0; 1123 1122 }
+1 -1
include/linux/fcntl.h
··· 8 8 /* List of all valid flags for the open/openat flags argument: */ 9 9 #define VALID_OPEN_FLAGS \ 10 10 (O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \ 11 - O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \ 11 + O_APPEND | O_NDELAY | O_NONBLOCK | __O_SYNC | O_DSYNC | \ 12 12 FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \ 13 13 O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE) 14 14
+5 -17
include/linux/fs.h
··· 3096 3096 3097 3097 extern int iterate_dir(struct file *, struct dir_context *); 3098 3098 3099 - extern int vfs_statx(int, const char __user *, int, struct kstat *, u32); 3100 - extern int vfs_statx_fd(unsigned int, struct kstat *, u32, unsigned int); 3099 + int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, 3100 + int flags); 3101 + int vfs_fstat(int fd, struct kstat *stat); 3101 3102 3102 3103 static inline int vfs_stat(const char __user *filename, struct kstat *stat) 3103 3104 { 3104 - return vfs_statx(AT_FDCWD, filename, AT_NO_AUTOMOUNT, 3105 - stat, STATX_BASIC_STATS); 3105 + return vfs_fstatat(AT_FDCWD, filename, stat, 0); 3106 3106 } 3107 3107 static inline int vfs_lstat(const char __user *name, struct kstat *stat) 3108 3108 { 3109 - return vfs_statx(AT_FDCWD, name, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, 3110 - stat, STATX_BASIC_STATS); 3109 + return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW); 3111 3110 } 3112 - static inline int vfs_fstatat(int dfd, const char __user *filename, 3113 - struct kstat *stat, int flags) 3114 - { 3115 - return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, 3116 - stat, STATX_BASIC_STATS); 3117 - } 3118 - static inline int vfs_fstat(int fd, struct kstat *stat) 3119 - { 3120 - return vfs_statx_fd(fd, stat, STATX_BASIC_STATS, 0); 3121 - } 3122 - 3123 3111 3124 3112 extern const char *vfs_get_link(struct dentry *, struct delayed_call *); 3125 3113 extern int vfs_readlink(struct dentry *, char __user *, int);
+2 -1
include/linux/mount.h
··· 30 30 #define MNT_NODIRATIME 0x10 31 31 #define MNT_RELATIME 0x20 32 32 #define MNT_READONLY 0x40 /* does the user want this to be r/o? */ 33 + #define MNT_NOSYMFOLLOW 0x80 33 34 34 35 #define MNT_SHRINKABLE 0x100 35 36 #define MNT_WRITE_HOLD 0x200 ··· 47 46 #define MNT_SHARED_MASK (MNT_UNBINDABLE) 48 47 #define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ 49 48 | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ 50 - | MNT_READONLY) 49 + | MNT_READONLY | MNT_NOSYMFOLLOW) 51 50 #define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME ) 52 51 53 52 #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
-2
include/linux/stat.h
··· 19 19 #include <linux/time.h> 20 20 #include <linux/uidgid.h> 21 21 22 - #define KSTAT_QUERY_FLAGS (AT_STATX_SYNC_TYPE) 23 - 24 22 struct kstat { 25 23 u32 result_mask; /* What fields the user got */ 26 24 umode_t mode;
+6
include/linux/statfs.h
··· 40 40 #define ST_NOATIME 0x0400 /* do not update access times */ 41 41 #define ST_NODIRATIME 0x0800 /* do not update directory access times */ 42 42 #define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ 43 + #define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */ 43 44 44 45 struct dentry; 45 46 extern int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid); 47 + 48 + static inline __kernel_fsid_t u64_to_fsid(u64 v) 49 + { 50 + return (__kernel_fsid_t){.val = {(u32)v, (u32)(v>>32)}}; 51 + } 46 52 47 53 #endif
+1
include/uapi/linux/mount.h
··· 16 16 #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 17 17 #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ 18 18 #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ 19 + #define MS_NOSYMFOLLOW 256 /* Do not follow symlinks */ 19 20 #define MS_NOATIME 1024 /* Do not update access times. */ 20 21 #define MS_NODIRATIME 2048 /* Do not update directory access times */ 21 22 #define MS_BIND 4096
+1
tools/testing/selftests/mount/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 unprivileged-remount-test 3 + nosymfollow-test
+2 -2
tools/testing/selftests/mount/Makefile
··· 3 3 CFLAGS = -Wall \ 4 4 -O2 5 5 6 - TEST_PROGS := run_tests.sh 7 - TEST_GEN_FILES := unprivileged-remount-test 6 + TEST_PROGS := run_unprivileged_remount.sh run_nosymfollow.sh 7 + TEST_GEN_FILES := unprivileged-remount-test nosymfollow-test 8 8 9 9 include ../lib.mk
+218
tools/testing/selftests/mount/nosymfollow-test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #define _GNU_SOURCE 3 + #include <errno.h> 4 + #include <fcntl.h> 5 + #include <limits.h> 6 + #include <sched.h> 7 + #include <stdarg.h> 8 + #include <stdbool.h> 9 + #include <stdio.h> 10 + #include <stdlib.h> 11 + #include <string.h> 12 + #include <sys/mount.h> 13 + #include <sys/stat.h> 14 + #include <sys/types.h> 15 + #include <sys/vfs.h> 16 + #include <unistd.h> 17 + 18 + #ifndef MS_NOSYMFOLLOW 19 + # define MS_NOSYMFOLLOW 256 /* Do not follow symlinks */ 20 + #endif 21 + 22 + #ifndef ST_NOSYMFOLLOW 23 + # define ST_NOSYMFOLLOW 0x2000 /* Do not follow symlinks */ 24 + #endif 25 + 26 + #define DATA "/tmp/data" 27 + #define LINK "/tmp/symlink" 28 + #define TMP "/tmp" 29 + 30 + static void die(char *fmt, ...) 31 + { 32 + va_list ap; 33 + 34 + va_start(ap, fmt); 35 + vfprintf(stderr, fmt, ap); 36 + va_end(ap); 37 + exit(EXIT_FAILURE); 38 + } 39 + 40 + static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, 41 + va_list ap) 42 + { 43 + ssize_t written; 44 + char buf[4096]; 45 + int buf_len; 46 + int fd; 47 + 48 + buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); 49 + if (buf_len < 0) 50 + die("vsnprintf failed: %s\n", strerror(errno)); 51 + 52 + if (buf_len >= sizeof(buf)) 53 + die("vsnprintf output truncated\n"); 54 + 55 + fd = open(filename, O_WRONLY); 56 + if (fd < 0) { 57 + if ((errno == ENOENT) && enoent_ok) 58 + return; 59 + die("open of %s failed: %s\n", filename, strerror(errno)); 60 + } 61 + 62 + written = write(fd, buf, buf_len); 63 + if (written != buf_len) { 64 + if (written >= 0) { 65 + die("short write to %s\n", filename); 66 + } else { 67 + die("write to %s failed: %s\n", 68 + filename, strerror(errno)); 69 + } 70 + } 71 + 72 + if (close(fd) != 0) 73 + die("close of %s failed: %s\n", filename, strerror(errno)); 74 + } 75 + 76 + static void maybe_write_file(char *filename, char *fmt, ...) 77 + { 78 + va_list ap; 79 + 80 + va_start(ap, fmt); 81 + vmaybe_write_file(true, filename, fmt, ap); 82 + va_end(ap); 83 + } 84 + 85 + static void write_file(char *filename, char *fmt, ...) 86 + { 87 + va_list ap; 88 + 89 + va_start(ap, fmt); 90 + vmaybe_write_file(false, filename, fmt, ap); 91 + va_end(ap); 92 + } 93 + 94 + static void create_and_enter_ns(void) 95 + { 96 + uid_t uid = getuid(); 97 + gid_t gid = getgid(); 98 + 99 + if (unshare(CLONE_NEWUSER) != 0) 100 + die("unshare(CLONE_NEWUSER) failed: %s\n", strerror(errno)); 101 + 102 + maybe_write_file("/proc/self/setgroups", "deny"); 103 + write_file("/proc/self/uid_map", "0 %d 1", uid); 104 + write_file("/proc/self/gid_map", "0 %d 1", gid); 105 + 106 + if (setgid(0) != 0) 107 + die("setgid(0) failed %s\n", strerror(errno)); 108 + if (setuid(0) != 0) 109 + die("setuid(0) failed %s\n", strerror(errno)); 110 + 111 + if (unshare(CLONE_NEWNS) != 0) 112 + die("unshare(CLONE_NEWNS) failed: %s\n", strerror(errno)); 113 + } 114 + 115 + static void setup_symlink(void) 116 + { 117 + int data, err; 118 + 119 + data = creat(DATA, O_RDWR); 120 + if (data < 0) 121 + die("creat failed: %s\n", strerror(errno)); 122 + 123 + err = symlink(DATA, LINK); 124 + if (err < 0) 125 + die("symlink failed: %s\n", strerror(errno)); 126 + 127 + if (close(data) != 0) 128 + die("close of %s failed: %s\n", DATA, strerror(errno)); 129 + } 130 + 131 + static void test_link_traversal(bool nosymfollow) 132 + { 133 + int link; 134 + 135 + link = open(LINK, 0, O_RDWR); 136 + if (nosymfollow) { 137 + if ((link != -1 || errno != ELOOP)) { 138 + die("link traversal unexpected result: %d, %s\n", 139 + link, strerror(errno)); 140 + } 141 + } else { 142 + if (link < 0) 143 + die("link traversal failed: %s\n", strerror(errno)); 144 + 145 + if (close(link) != 0) 146 + die("close of link failed: %s\n", strerror(errno)); 147 + } 148 + } 149 + 150 + static void test_readlink(void) 151 + { 152 + char buf[4096]; 153 + ssize_t ret; 154 + 155 + bzero(buf, sizeof(buf)); 156 + 157 + ret = readlink(LINK, buf, sizeof(buf)); 158 + if (ret < 0) 159 + die("readlink failed: %s\n", strerror(errno)); 160 + if (strcmp(buf, DATA) != 0) 161 + die("readlink strcmp failed: '%s' '%s'\n", buf, DATA); 162 + } 163 + 164 + static void test_realpath(void) 165 + { 166 + char *path = realpath(LINK, NULL); 167 + 168 + if (!path) 169 + die("realpath failed: %s\n", strerror(errno)); 170 + if (strcmp(path, DATA) != 0) 171 + die("realpath strcmp failed\n"); 172 + 173 + free(path); 174 + } 175 + 176 + static void test_statfs(bool nosymfollow) 177 + { 178 + struct statfs buf; 179 + int ret; 180 + 181 + ret = statfs(TMP, &buf); 182 + if (ret) 183 + die("statfs failed: %s\n", strerror(errno)); 184 + 185 + if (nosymfollow) { 186 + if ((buf.f_flags & ST_NOSYMFOLLOW) == 0) 187 + die("ST_NOSYMFOLLOW not set on %s\n", TMP); 188 + } else { 189 + if ((buf.f_flags & ST_NOSYMFOLLOW) != 0) 190 + die("ST_NOSYMFOLLOW set on %s\n", TMP); 191 + } 192 + } 193 + 194 + static void run_tests(bool nosymfollow) 195 + { 196 + test_link_traversal(nosymfollow); 197 + test_readlink(); 198 + test_realpath(); 199 + test_statfs(nosymfollow); 200 + } 201 + 202 + int main(int argc, char **argv) 203 + { 204 + create_and_enter_ns(); 205 + 206 + if (mount("testing", TMP, "ramfs", 0, NULL) != 0) 207 + die("mount failed: %s\n", strerror(errno)); 208 + 209 + setup_symlink(); 210 + run_tests(false); 211 + 212 + if (mount("testing", TMP, "ramfs", MS_REMOUNT|MS_NOSYMFOLLOW, NULL) != 0) 213 + die("remount failed: %s\n", strerror(errno)); 214 + 215 + run_tests(true); 216 + 217 + return EXIT_SUCCESS; 218 + }
+4
tools/testing/selftests/mount/run_nosymfollow.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + ./nosymfollow-test
tools/testing/selftests/mount/run_tests.sh tools/testing/selftests/mount/run_unprivileged_remount.sh