Skip to content

Commit e7c375b

Browse files
committed
Merge tag 'vfs-6.18-rc7.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Fix unitialized variable in statmount_string() - Fix hostfs mounting when passing host root during boot - Fix dynamic lookup to fail on cell lookup failure - Fix missing file type when reading bfs inodes from disk - Enforce checking of sb_min_blocksize() calls and update all callers accordingly - Restore write access before closing files opened by open_exec() in binfmt_misc - Always freeze efivarfs during suspend/hibernate cycles - Fix statmount()'s and listmount()'s grab_requested_mnt_ns() helper to actually allow mount namespace file descriptor in addition to mount namespace ids - Fix tmpfs remount when noswap is specified - Switch Landlock to iput_not_last() to remove false-positives from might_sleep() annotations in iput() - Remove dead node_to_mnt_ns() code - Ensure that per-queue kobjects are successfully created * tag 'vfs-6.18-rc7.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs: landlock: fix splats from iput() after it started calling might_sleep() fs: add iput_not_last() shmem: fix tmpfs reconfiguration (remount) when noswap is set fs/namespace: correctly handle errors returned by grab_requested_mnt_ns power: always freeze efivarfs binfmt_misc: restore write access before closing files opened by open_exec() block: add __must_check attribute to sb_min_blocksize() virtio-fs: fix incorrect check for fsvq->kobj xfs: check the return value of sb_min_blocksize() in xfs_fs_fill_super isofs: check the return value of sb_min_blocksize() in isofs_fill_super exfat: check return value of sb_min_blocksize in exfat_read_boot_sector vfat: fix missing sb_min_blocksize() return value checks mnt: Remove dead code which might prevent from building bfs: Reconstruct file type when loading from disk afs: Fix dynamic lookup to fail on cell lookup failure hostfs: Fix only passing host root in boot stage with new mount fs: Fix uninitialized 'offp' in statmount_string()
2 parents 418592a + e9d50b7 commit e7c375b

File tree

26 files changed

+206
-91
lines changed

26 files changed

+206
-91
lines changed

block/bdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ int sb_set_blocksize(struct super_block *sb, int size)
231231

232232
EXPORT_SYMBOL(sb_set_blocksize);
233233

234-
int sb_min_blocksize(struct super_block *sb, int size)
234+
int __must_check sb_min_blocksize(struct super_block *sb, int size)
235235
{
236236
int minsize = bdev_logical_block_size(sb->s_bdev);
237237
if (size < minsize)

fs/afs/cell.c

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
229229
* @name: The name of the cell.
230230
* @namesz: The strlen of the cell name.
231231
* @vllist: A colon/comma separated list of numeric IP addresses or NULL.
232-
* @excl: T if an error should be given if the cell name already exists.
232+
* @reason: The reason we're doing the lookup
233233
* @trace: The reason to be logged if the lookup is successful.
234234
*
235235
* Look up a cell record by name and query the DNS for VL server addresses if
@@ -239,20 +239,27 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
239239
*/
240240
struct afs_cell *afs_lookup_cell(struct afs_net *net,
241241
const char *name, unsigned int namesz,
242-
const char *vllist, bool excl,
242+
const char *vllist,
243+
enum afs_lookup_cell_for reason,
243244
enum afs_cell_trace trace)
244245
{
245246
struct afs_cell *cell, *candidate, *cursor;
246247
struct rb_node *parent, **pp;
247248
enum afs_cell_state state;
248249
int ret, n;
249250

250-
_enter("%s,%s", name, vllist);
251+
_enter("%s,%s,%u", name, vllist, reason);
251252

252-
if (!excl) {
253+
if (reason != AFS_LOOKUP_CELL_PRELOAD) {
253254
cell = afs_find_cell(net, name, namesz, trace);
254-
if (!IS_ERR(cell))
255+
if (!IS_ERR(cell)) {
256+
if (reason == AFS_LOOKUP_CELL_DYNROOT)
257+
goto no_wait;
258+
if (cell->state == AFS_CELL_SETTING_UP ||
259+
cell->state == AFS_CELL_UNLOOKED)
260+
goto lookup_cell;
255261
goto wait_for_cell;
262+
}
256263
}
257264

258265
/* Assume we're probably going to create a cell and preallocate and
@@ -298,34 +305,77 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
298305
rb_insert_color(&cell->net_node, &net->cells);
299306
up_write(&net->cells_lock);
300307

301-
afs_queue_cell(cell, afs_cell_trace_queue_new);
308+
lookup_cell:
309+
if (reason != AFS_LOOKUP_CELL_PRELOAD &&
310+
reason != AFS_LOOKUP_CELL_ROOTCELL) {
311+
set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
312+
afs_queue_cell(cell, afs_cell_trace_queue_new);
313+
}
302314

303315
wait_for_cell:
304-
_debug("wait_for_cell");
305316
state = smp_load_acquire(&cell->state); /* vs error */
306-
if (state != AFS_CELL_ACTIVE &&
307-
state != AFS_CELL_DEAD) {
317+
switch (state) {
318+
case AFS_CELL_ACTIVE:
319+
case AFS_CELL_DEAD:
320+
break;
321+
case AFS_CELL_UNLOOKED:
322+
default:
323+
if (reason == AFS_LOOKUP_CELL_PRELOAD ||
324+
reason == AFS_LOOKUP_CELL_ROOTCELL)
325+
break;
326+
_debug("wait_for_cell");
308327
afs_see_cell(cell, afs_cell_trace_wait);
309328
wait_var_event(&cell->state,
310329
({
311330
state = smp_load_acquire(&cell->state); /* vs error */
312331
state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
313332
}));
333+
_debug("waited_for_cell %d %d", cell->state, cell->error);
314334
}
315335

336+
no_wait:
316337
/* Check the state obtained from the wait check. */
338+
state = smp_load_acquire(&cell->state); /* vs error */
317339
if (state == AFS_CELL_DEAD) {
318340
ret = cell->error;
319341
goto error;
320342
}
343+
if (state == AFS_CELL_ACTIVE) {
344+
switch (cell->dns_status) {
345+
case DNS_LOOKUP_NOT_DONE:
346+
if (cell->dns_source == DNS_RECORD_FROM_CONFIG) {
347+
ret = 0;
348+
break;
349+
}
350+
fallthrough;
351+
default:
352+
ret = -EIO;
353+
goto error;
354+
case DNS_LOOKUP_GOOD:
355+
case DNS_LOOKUP_GOOD_WITH_BAD:
356+
ret = 0;
357+
break;
358+
case DNS_LOOKUP_GOT_NOT_FOUND:
359+
ret = -ENOENT;
360+
goto error;
361+
case DNS_LOOKUP_BAD:
362+
ret = -EREMOTEIO;
363+
goto error;
364+
case DNS_LOOKUP_GOT_LOCAL_FAILURE:
365+
case DNS_LOOKUP_GOT_TEMP_FAILURE:
366+
case DNS_LOOKUP_GOT_NS_FAILURE:
367+
ret = -EDESTADDRREQ;
368+
goto error;
369+
}
370+
}
321371

322372
_leave(" = %p [cell]", cell);
323373
return cell;
324374

325375
cell_already_exists:
326376
_debug("cell exists");
327377
cell = cursor;
328-
if (excl) {
378+
if (reason == AFS_LOOKUP_CELL_PRELOAD) {
329379
ret = -EEXIST;
330380
} else {
331381
afs_use_cell(cursor, trace);
@@ -384,7 +434,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
384434
return -EINVAL;
385435

386436
/* allocate a cell record for the root/workstation cell */
387-
new_root = afs_lookup_cell(net, rootcell, len, vllist, false,
437+
new_root = afs_lookup_cell(net, rootcell, len, vllist,
438+
AFS_LOOKUP_CELL_ROOTCELL,
388439
afs_cell_trace_use_lookup_ws);
389440
if (IS_ERR(new_root)) {
390441
_leave(" = %ld", PTR_ERR(new_root));
@@ -777,6 +828,7 @@ static bool afs_manage_cell(struct afs_cell *cell)
777828
switch (cell->state) {
778829
case AFS_CELL_SETTING_UP:
779830
goto set_up_cell;
831+
case AFS_CELL_UNLOOKED:
780832
case AFS_CELL_ACTIVE:
781833
goto cell_is_active;
782834
case AFS_CELL_REMOVING:
@@ -797,7 +849,7 @@ static bool afs_manage_cell(struct afs_cell *cell)
797849
goto remove_cell;
798850
}
799851

800-
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
852+
afs_set_cell_state(cell, AFS_CELL_UNLOOKED);
801853

802854
cell_is_active:
803855
if (afs_has_cell_expired(cell, &next_manage))
@@ -807,6 +859,8 @@ static bool afs_manage_cell(struct afs_cell *cell)
807859
ret = afs_update_cell(cell);
808860
if (ret < 0)
809861
cell->error = ret;
862+
if (cell->state == AFS_CELL_UNLOOKED)
863+
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
810864
}
811865

812866
if (next_manage < TIME64_MAX && cell->net->live) {

fs/afs/dynroot.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ static struct dentry *afs_dynroot_lookup_cell(struct inode *dir, struct dentry *
108108
dotted = true;
109109
}
110110

111-
cell = afs_lookup_cell(net, name, len, NULL, false,
111+
cell = afs_lookup_cell(net, name, len, NULL,
112+
AFS_LOOKUP_CELL_DYNROOT,
112113
afs_cell_trace_use_lookup_dynroot);
113114
if (IS_ERR(cell)) {
114115
ret = PTR_ERR(cell);

fs/afs/internal.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ extern const char afs_init_sysname[];
343343

344344
enum afs_cell_state {
345345
AFS_CELL_SETTING_UP,
346+
AFS_CELL_UNLOOKED,
346347
AFS_CELL_ACTIVE,
347348
AFS_CELL_REMOVING,
348349
AFS_CELL_DEAD,
@@ -1049,9 +1050,18 @@ static inline bool afs_cb_is_broken(unsigned int cb_break,
10491050
extern int afs_cell_init(struct afs_net *, const char *);
10501051
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
10511052
enum afs_cell_trace);
1053+
enum afs_lookup_cell_for {
1054+
AFS_LOOKUP_CELL_DYNROOT,
1055+
AFS_LOOKUP_CELL_MOUNTPOINT,
1056+
AFS_LOOKUP_CELL_DIRECT_MOUNT,
1057+
AFS_LOOKUP_CELL_PRELOAD,
1058+
AFS_LOOKUP_CELL_ROOTCELL,
1059+
AFS_LOOKUP_CELL_ALIAS_CHECK,
1060+
};
10521061
struct afs_cell *afs_lookup_cell(struct afs_net *net,
10531062
const char *name, unsigned int namesz,
1054-
const char *vllist, bool excl,
1063+
const char *vllist,
1064+
enum afs_lookup_cell_for reason,
10551065
enum afs_cell_trace trace);
10561066
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
10571067
void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);

fs/afs/mntpt.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
107107
if (size > AFS_MAXCELLNAME)
108108
return -ENAMETOOLONG;
109109

110-
cell = afs_lookup_cell(ctx->net, p, size, NULL, false,
110+
cell = afs_lookup_cell(ctx->net, p, size, NULL,
111+
AFS_LOOKUP_CELL_MOUNTPOINT,
111112
afs_cell_trace_use_lookup_mntpt);
112113
if (IS_ERR(cell)) {
113114
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);

fs/afs/proc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ static int afs_proc_cells_write(struct file *file, char *buf, size_t size)
122122
if (strcmp(buf, "add") == 0) {
123123
struct afs_cell *cell;
124124

125-
cell = afs_lookup_cell(net, name, strlen(name), args, true,
125+
cell = afs_lookup_cell(net, name, strlen(name), args,
126+
AFS_LOOKUP_CELL_PRELOAD,
126127
afs_cell_trace_use_lookup_add);
127128
if (IS_ERR(cell)) {
128129
ret = PTR_ERR(cell);

fs/afs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
290290
/* lookup the cell record */
291291
if (cellname) {
292292
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
293-
NULL, false,
293+
NULL, AFS_LOOKUP_CELL_DIRECT_MOUNT,
294294
afs_cell_trace_use_lookup_mount);
295295
if (IS_ERR(cell)) {
296296
pr_err("kAFS: unable to lookup cell '%*.*s'\n",

fs/afs/vl_alias.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ static int yfs_check_canonical_cell_name(struct afs_cell *cell, struct key *key)
269269
if (!name_len || name_len > AFS_MAXCELLNAME)
270270
master = ERR_PTR(-EOPNOTSUPP);
271271
else
272-
master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false,
272+
master = afs_lookup_cell(cell->net, cell_name, name_len, NULL,
273+
AFS_LOOKUP_CELL_ALIAS_CHECK,
273274
afs_cell_trace_use_lookup_canonical);
274275
kfree(cell_name);
275276
if (IS_ERR(master))

fs/bfs/inode.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,19 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
6161
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
6262
di = (struct bfs_inode *)bh->b_data + off;
6363

64-
inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
64+
/*
65+
* https://martin.hinner.info/fs/bfs/bfs-structure.html explains that
66+
* BFS in SCO UnixWare environment used only lower 9 bits of di->i_mode
67+
* value. This means that, although bfs_write_inode() saves whole
68+
* inode->i_mode bits (which include S_IFMT bits and S_IS{UID,GID,VTX}
69+
* bits), middle 7 bits of di->i_mode value can be garbage when these
70+
* bits were not saved by bfs_write_inode().
71+
* Since we can't tell whether middle 7 bits are garbage, use only
72+
* lower 12 bits (i.e. tolerate S_IS{UID,GID,VTX} bits possibly being
73+
* garbage) and reconstruct S_IFMT bits for Linux environment from
74+
* di->i_vtype value.
75+
*/
76+
inode->i_mode = 0x00000FFF & le32_to_cpu(di->i_mode);
6577
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
6678
inode->i_mode |= S_IFDIR;
6779
inode->i_op = &bfs_dir_inops;
@@ -71,6 +83,11 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
7183
inode->i_op = &bfs_file_inops;
7284
inode->i_fop = &bfs_file_operations;
7385
inode->i_mapping->a_ops = &bfs_aops;
86+
} else {
87+
brelse(bh);
88+
printf("Unknown vtype=%u %s:%08lx\n",
89+
le32_to_cpu(di->i_vtype), inode->i_sb->s_id, ino);
90+
goto error;
7491
}
7592

7693
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);

fs/binfmt_misc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,8 +837,10 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
837837
inode_unlock(d_inode(root));
838838

839839
if (err) {
840-
if (f)
840+
if (f) {
841+
exe_file_allow_write_access(f);
841842
filp_close(f, NULL);
843+
}
842844
kfree(e);
843845
return err;
844846
}

0 commit comments

Comments
 (0)