| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
|---|
| 3 | 4 | * Copyright 2005-2006 Ian Kent <raven@themaw.net> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This file is part of the Linux kernel and is made available under |
|---|
| 6 | | - * the terms of the GNU General Public License, version 2, or at your |
|---|
| 7 | | - * option, any later version, incorporated herein by reference. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #include <linux/seq_file.h> |
|---|
| .. | .. |
|---|
| 36 | 33 | |
|---|
| 37 | 34 | void autofs_free_ino(struct autofs_info *ino) |
|---|
| 38 | 35 | { |
|---|
| 39 | | - kfree(ino); |
|---|
| 36 | + kfree_rcu(ino, rcu); |
|---|
| 40 | 37 | } |
|---|
| 41 | 38 | |
|---|
| 42 | 39 | void autofs_kill_sb(struct super_block *sb) |
|---|
| .. | .. |
|---|
| 82 | 79 | seq_printf(m, ",maxproto=%d", sbi->max_proto); |
|---|
| 83 | 80 | |
|---|
| 84 | 81 | if (autofs_type_offset(sbi->type)) |
|---|
| 85 | | - seq_printf(m, ",offset"); |
|---|
| 82 | + seq_puts(m, ",offset"); |
|---|
| 86 | 83 | else if (autofs_type_direct(sbi->type)) |
|---|
| 87 | | - seq_printf(m, ",direct"); |
|---|
| 84 | + seq_puts(m, ",direct"); |
|---|
| 88 | 85 | else |
|---|
| 89 | | - seq_printf(m, ",indirect"); |
|---|
| 86 | + seq_puts(m, ",indirect"); |
|---|
| 87 | + if (sbi->flags & AUTOFS_SBI_STRICTEXPIRE) |
|---|
| 88 | + seq_puts(m, ",strictexpire"); |
|---|
| 89 | + if (sbi->flags & AUTOFS_SBI_IGNORE) |
|---|
| 90 | + seq_puts(m, ",ignore"); |
|---|
| 90 | 91 | #ifdef CONFIG_CHECKPOINT_RESTORE |
|---|
| 91 | 92 | if (sbi->pipe) |
|---|
| 92 | 93 | seq_printf(m, ",pipe_ino=%ld", file_inode(sbi->pipe)->i_ino); |
|---|
| 93 | 94 | else |
|---|
| 94 | | - seq_printf(m, ",pipe_ino=-1"); |
|---|
| 95 | + seq_puts(m, ",pipe_ino=-1"); |
|---|
| 95 | 96 | #endif |
|---|
| 96 | 97 | return 0; |
|---|
| 97 | 98 | } |
|---|
| .. | .. |
|---|
| 109 | 110 | }; |
|---|
| 110 | 111 | |
|---|
| 111 | 112 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, |
|---|
| 112 | | - Opt_indirect, Opt_direct, Opt_offset}; |
|---|
| 113 | + Opt_indirect, Opt_direct, Opt_offset, Opt_strictexpire, |
|---|
| 114 | + Opt_ignore}; |
|---|
| 113 | 115 | |
|---|
| 114 | 116 | static const match_table_t tokens = { |
|---|
| 115 | 117 | {Opt_fd, "fd=%u"}, |
|---|
| .. | .. |
|---|
| 121 | 123 | {Opt_indirect, "indirect"}, |
|---|
| 122 | 124 | {Opt_direct, "direct"}, |
|---|
| 123 | 125 | {Opt_offset, "offset"}, |
|---|
| 126 | + {Opt_strictexpire, "strictexpire"}, |
|---|
| 127 | + {Opt_ignore, "ignore"}, |
|---|
| 124 | 128 | {Opt_err, NULL} |
|---|
| 125 | 129 | }; |
|---|
| 126 | 130 | |
|---|
| 127 | | -static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid, |
|---|
| 128 | | - int *pgrp, bool *pgrp_set, unsigned int *type, |
|---|
| 129 | | - int *minproto, int *maxproto) |
|---|
| 131 | +static int parse_options(char *options, |
|---|
| 132 | + struct inode *root, int *pgrp, bool *pgrp_set, |
|---|
| 133 | + struct autofs_sb_info *sbi) |
|---|
| 130 | 134 | { |
|---|
| 131 | 135 | char *p; |
|---|
| 132 | 136 | substring_t args[MAX_OPT_ARGS]; |
|---|
| 133 | 137 | int option; |
|---|
| 138 | + int pipefd = -1; |
|---|
| 139 | + kuid_t uid; |
|---|
| 140 | + kgid_t gid; |
|---|
| 134 | 141 | |
|---|
| 135 | | - *uid = current_uid(); |
|---|
| 136 | | - *gid = current_gid(); |
|---|
| 142 | + root->i_uid = current_uid(); |
|---|
| 143 | + root->i_gid = current_gid(); |
|---|
| 137 | 144 | |
|---|
| 138 | | - *minproto = AUTOFS_MIN_PROTO_VERSION; |
|---|
| 139 | | - *maxproto = AUTOFS_MAX_PROTO_VERSION; |
|---|
| 145 | + sbi->min_proto = AUTOFS_MIN_PROTO_VERSION; |
|---|
| 146 | + sbi->max_proto = AUTOFS_MAX_PROTO_VERSION; |
|---|
| 140 | 147 | |
|---|
| 141 | | - *pipefd = -1; |
|---|
| 148 | + sbi->pipefd = -1; |
|---|
| 142 | 149 | |
|---|
| 143 | 150 | if (!options) |
|---|
| 144 | 151 | return 1; |
|---|
| .. | .. |
|---|
| 152 | 159 | token = match_token(p, tokens, args); |
|---|
| 153 | 160 | switch (token) { |
|---|
| 154 | 161 | case Opt_fd: |
|---|
| 155 | | - if (match_int(args, pipefd)) |
|---|
| 162 | + if (match_int(args, &pipefd)) |
|---|
| 156 | 163 | return 1; |
|---|
| 164 | + sbi->pipefd = pipefd; |
|---|
| 157 | 165 | break; |
|---|
| 158 | 166 | case Opt_uid: |
|---|
| 159 | 167 | if (match_int(args, &option)) |
|---|
| 160 | 168 | return 1; |
|---|
| 161 | | - *uid = make_kuid(current_user_ns(), option); |
|---|
| 162 | | - if (!uid_valid(*uid)) |
|---|
| 169 | + uid = make_kuid(current_user_ns(), option); |
|---|
| 170 | + if (!uid_valid(uid)) |
|---|
| 163 | 171 | return 1; |
|---|
| 172 | + root->i_uid = uid; |
|---|
| 164 | 173 | break; |
|---|
| 165 | 174 | case Opt_gid: |
|---|
| 166 | 175 | if (match_int(args, &option)) |
|---|
| 167 | 176 | return 1; |
|---|
| 168 | | - *gid = make_kgid(current_user_ns(), option); |
|---|
| 169 | | - if (!gid_valid(*gid)) |
|---|
| 177 | + gid = make_kgid(current_user_ns(), option); |
|---|
| 178 | + if (!gid_valid(gid)) |
|---|
| 170 | 179 | return 1; |
|---|
| 180 | + root->i_gid = gid; |
|---|
| 171 | 181 | break; |
|---|
| 172 | 182 | case Opt_pgrp: |
|---|
| 173 | 183 | if (match_int(args, &option)) |
|---|
| .. | .. |
|---|
| 178 | 188 | case Opt_minproto: |
|---|
| 179 | 189 | if (match_int(args, &option)) |
|---|
| 180 | 190 | return 1; |
|---|
| 181 | | - *minproto = option; |
|---|
| 191 | + sbi->min_proto = option; |
|---|
| 182 | 192 | break; |
|---|
| 183 | 193 | case Opt_maxproto: |
|---|
| 184 | 194 | if (match_int(args, &option)) |
|---|
| 185 | 195 | return 1; |
|---|
| 186 | | - *maxproto = option; |
|---|
| 196 | + sbi->max_proto = option; |
|---|
| 187 | 197 | break; |
|---|
| 188 | 198 | case Opt_indirect: |
|---|
| 189 | | - set_autofs_type_indirect(type); |
|---|
| 199 | + set_autofs_type_indirect(&sbi->type); |
|---|
| 190 | 200 | break; |
|---|
| 191 | 201 | case Opt_direct: |
|---|
| 192 | | - set_autofs_type_direct(type); |
|---|
| 202 | + set_autofs_type_direct(&sbi->type); |
|---|
| 193 | 203 | break; |
|---|
| 194 | 204 | case Opt_offset: |
|---|
| 195 | | - set_autofs_type_offset(type); |
|---|
| 205 | + set_autofs_type_offset(&sbi->type); |
|---|
| 206 | + break; |
|---|
| 207 | + case Opt_strictexpire: |
|---|
| 208 | + sbi->flags |= AUTOFS_SBI_STRICTEXPIRE; |
|---|
| 209 | + break; |
|---|
| 210 | + case Opt_ignore: |
|---|
| 211 | + sbi->flags |= AUTOFS_SBI_IGNORE; |
|---|
| 196 | 212 | break; |
|---|
| 197 | 213 | default: |
|---|
| 198 | 214 | return 1; |
|---|
| 199 | 215 | } |
|---|
| 200 | 216 | } |
|---|
| 201 | | - return (*pipefd < 0); |
|---|
| 217 | + return (sbi->pipefd < 0); |
|---|
| 202 | 218 | } |
|---|
| 203 | 219 | |
|---|
| 204 | 220 | int autofs_fill_super(struct super_block *s, void *data, int silent) |
|---|
| .. | .. |
|---|
| 206 | 222 | struct inode *root_inode; |
|---|
| 207 | 223 | struct dentry *root; |
|---|
| 208 | 224 | struct file *pipe; |
|---|
| 209 | | - int pipefd; |
|---|
| 210 | 225 | struct autofs_sb_info *sbi; |
|---|
| 211 | 226 | struct autofs_info *ino; |
|---|
| 212 | 227 | int pgrp = 0; |
|---|
| .. | .. |
|---|
| 222 | 237 | sbi->magic = AUTOFS_SBI_MAGIC; |
|---|
| 223 | 238 | sbi->pipefd = -1; |
|---|
| 224 | 239 | sbi->pipe = NULL; |
|---|
| 225 | | - sbi->catatonic = 1; |
|---|
| 226 | 240 | sbi->exp_timeout = 0; |
|---|
| 227 | 241 | sbi->oz_pgrp = NULL; |
|---|
| 228 | 242 | sbi->sb = s; |
|---|
| 229 | 243 | sbi->version = 0; |
|---|
| 230 | 244 | sbi->sub_version = 0; |
|---|
| 245 | + sbi->flags = AUTOFS_SBI_CATATONIC; |
|---|
| 231 | 246 | set_autofs_type_indirect(&sbi->type); |
|---|
| 232 | 247 | sbi->min_proto = 0; |
|---|
| 233 | 248 | sbi->max_proto = 0; |
|---|
| .. | .. |
|---|
| 264 | 279 | root->d_fsdata = ino; |
|---|
| 265 | 280 | |
|---|
| 266 | 281 | /* Can this call block? */ |
|---|
| 267 | | - if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid, |
|---|
| 268 | | - &pgrp, &pgrp_set, &sbi->type, &sbi->min_proto, |
|---|
| 269 | | - &sbi->max_proto)) { |
|---|
| 282 | + if (parse_options(data, root_inode, &pgrp, &pgrp_set, sbi)) { |
|---|
| 270 | 283 | pr_err("called with bogus options\n"); |
|---|
| 271 | 284 | goto fail_dput; |
|---|
| 272 | 285 | } |
|---|
| .. | .. |
|---|
| 305 | 318 | root_inode->i_fop = &autofs_root_operations; |
|---|
| 306 | 319 | root_inode->i_op = &autofs_dir_inode_operations; |
|---|
| 307 | 320 | |
|---|
| 308 | | - pr_debug("pipe fd = %d, pgrp = %u\n", pipefd, pid_nr(sbi->oz_pgrp)); |
|---|
| 309 | | - pipe = fget(pipefd); |
|---|
| 321 | + pr_debug("pipe fd = %d, pgrp = %u\n", |
|---|
| 322 | + sbi->pipefd, pid_nr(sbi->oz_pgrp)); |
|---|
| 323 | + pipe = fget(sbi->pipefd); |
|---|
| 310 | 324 | |
|---|
| 311 | 325 | if (!pipe) { |
|---|
| 312 | 326 | pr_err("could not open pipe file descriptor\n"); |
|---|
| .. | .. |
|---|
| 316 | 330 | if (ret < 0) |
|---|
| 317 | 331 | goto fail_fput; |
|---|
| 318 | 332 | sbi->pipe = pipe; |
|---|
| 319 | | - sbi->pipefd = pipefd; |
|---|
| 320 | | - sbi->catatonic = 0; |
|---|
| 333 | + sbi->flags &= ~AUTOFS_SBI_CATATONIC; |
|---|
| 321 | 334 | |
|---|
| 322 | 335 | /* |
|---|
| 323 | 336 | * Success! Install the root dentry now to indicate completion. |
|---|