]>
git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - fs/aufs/rdu.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2005-2020 Junjiro R. Okajima
5 * This program, aufs is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * readdir in userspace.
23 #include <linux/compat.h>
24 #include <linux/fs_stack.h>
25 #include <linux/security.h>
28 /* bits for struct aufs_rdu.flags */
29 #define AuRdu_CALLED 1
30 #define AuRdu_CONT (1 << 1)
31 #define AuRdu_FULL (1 << 2)
32 #define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
33 #define au_fset_rdu(flags, name) \
34 do { (flags) |= AuRdu_##name; } while (0)
35 #define au_fclr_rdu(flags, name) \
36 do { (flags) &= ~AuRdu_##name; } while (0)
39 struct dir_context ctx
;
41 union au_rdu_ent_ul ent
;
44 struct super_block
*sb
;
48 static int au_rdu_fill(struct dir_context
*ctx
, const char *name
, int nlen
,
49 loff_t offset
, u64 h_ino
, unsigned int d_type
)
52 struct au_rdu_arg
*arg
= container_of(ctx
, struct au_rdu_arg
, ctx
);
53 struct aufs_rdu
*rdu
= arg
->rdu
;
54 struct au_rdu_ent ent
;
58 au_fset_rdu(rdu
->cookie
.flags
, CALLED
);
59 len
= au_rdu_len(nlen
);
60 if (arg
->ent
.ul
+ len
< arg
->end
) {
62 ent
.bindex
= rdu
->cookie
.bindex
;
65 if (unlikely(nlen
> AUFS_MAX_NAMELEN
))
66 ent
.type
= DT_UNKNOWN
;
68 /* unnecessary to support mmap_sem since this is a dir */
70 if (copy_to_user(arg
->ent
.e
, &ent
, sizeof(ent
)))
72 if (copy_to_user(arg
->ent
.e
->name
, name
, nlen
))
74 /* the terminating NULL */
75 if (__put_user(0, arg
->ent
.e
->name
+ nlen
))
78 /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
83 au_fset_rdu(rdu
->cookie
.flags
, FULL
);
89 /* AuTraceErr(err); */
93 static int au_rdu_do(struct file
*h_file
, struct au_rdu_arg
*arg
)
97 struct au_rdu_cookie
*cookie
= &arg
->rdu
->cookie
;
99 /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
100 offset
= vfsub_llseek(h_file
, cookie
->h_pos
, SEEK_SET
);
102 if (unlikely(offset
!= cookie
->h_pos
))
108 au_fclr_rdu(cookie
->flags
, CALLED
);
110 err
= vfsub_iterate_dir(h_file
, &arg
->ctx
);
114 && au_ftest_rdu(cookie
->flags
, CALLED
)
115 && !au_ftest_rdu(cookie
->flags
, FULL
));
116 cookie
->h_pos
= h_file
->f_pos
;
123 static int au_rdu(struct file
*file
, struct aufs_rdu
*rdu
)
127 struct au_rdu_arg arg
= {
132 struct dentry
*dentry
;
135 struct au_rdu_cookie
*cookie
= &rdu
->cookie
;
138 err
= !access_ok(rdu
->ent
.e
, rdu
->sz
);
145 rdu
->tail
= rdu
->ent
;
149 arg
.end
= arg
.ent
.ul
;
153 if (unlikely(!file
->f_op
->iterate
&& !file
->f_op
->iterate_shared
))
156 err
= security_file_permission(file
, MAY_READ
);
161 dentry
= file
->f_path
.dentry
;
162 inode
= d_inode(dentry
);
163 inode_lock_shared(inode
);
165 arg
.sb
= inode
->i_sb
;
166 err
= si_read_lock(arg
.sb
, AuLock_FLUSH
| AuLock_NOPLM
);
169 err
= au_alive_dir(dentry
);
176 if (unlikely(au_ftest_rdu(cookie
->flags
, CONT
)
177 && cookie
->generation
!= au_figen(file
)))
182 rdu
->blk
= au_sbi(arg
.sb
)->si_rdblk
;
184 rdu
->blk
= au_dir_size(file
, /*dentry*/NULL
);
186 bbot
= au_fbtop(file
);
187 if (cookie
->bindex
< bbot
)
188 cookie
->bindex
= bbot
;
189 bbot
= au_fbbot_dir(file
);
190 /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
191 for (; !err
&& cookie
->bindex
<= bbot
;
192 cookie
->bindex
++, cookie
->h_pos
= 0) {
193 h_file
= au_hf_dir(file
, cookie
->bindex
);
197 au_fclr_rdu(cookie
->flags
, FULL
);
198 err
= au_rdu_do(h_file
, &arg
);
200 if (unlikely(au_ftest_rdu(cookie
->flags
, FULL
) || err
))
203 AuDbg("rent %llu\n", rdu
->rent
);
205 if (!err
&& !au_ftest_rdu(cookie
->flags
, CONT
)) {
206 rdu
->shwh
= !!au_opt_test(au_sbi(arg
.sb
)->si_mntflags
, SHWH
);
207 au_fset_rdu(cookie
->flags
, CONT
);
208 cookie
->generation
= au_figen(file
);
211 ii_read_lock_child(inode
);
212 fsstack_copy_attr_atime(inode
, au_h_iptr(inode
, au_ibtop(inode
)));
213 ii_read_unlock(inode
);
216 fi_read_unlock(file
);
218 si_read_unlock(arg
.sb
);
220 inode_unlock_shared(inode
);
226 static int au_rdu_ino(struct file
*file
, struct aufs_rdu
*rdu
)
230 unsigned long long nent
;
231 union au_rdu_ent_ul
*u
;
232 struct au_rdu_ent ent
;
233 struct super_block
*sb
;
238 sb
= file
->f_path
.dentry
->d_sb
;
239 si_read_lock(sb
, AuLock_FLUSH
);
241 /* unnecessary to support mmap_sem since this is a dir */
242 err
= copy_from_user(&ent
, u
->e
, sizeof(ent
));
245 err
= !access_ok(&u
->e
->ino
, sizeof(ino
));
252 /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
254 err
= au_ino(sb
, ent
.bindex
, ent
.ino
, ent
.type
, &ino
);
256 err
= au_wh_ino(sb
, ent
.bindex
, ent
.ino
, ent
.type
,
263 err
= __put_user(ino
, &u
->e
->ino
);
269 u
->ul
+= au_rdu_len(ent
.nlen
);
276 /* ---------------------------------------------------------------------- */
278 static int au_rdu_verify(struct aufs_rdu
*rdu
)
280 AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
281 "%llu, b%d, 0x%x, g%u}\n",
282 rdu
->sz
, rdu
->ent
.e
, rdu
->verify
[AufsCtlRduV_SZ
],
284 rdu
->rent
, rdu
->shwh
, rdu
->full
,
285 rdu
->cookie
.h_pos
, rdu
->cookie
.bindex
, rdu
->cookie
.flags
,
286 rdu
->cookie
.generation
);
288 if (rdu
->verify
[AufsCtlRduV_SZ
] == sizeof(*rdu
))
292 rdu
->verify
[AufsCtlRduV_SZ
], (unsigned int)sizeof(*rdu
));
296 long au_rdu_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
300 void __user
*p
= (void __user
*)arg
;
302 err
= copy_from_user(&rdu
, p
, sizeof(rdu
));
308 err
= au_rdu_verify(&rdu
);
314 err
= au_rdu(file
, &rdu
);
318 e
= copy_to_user(p
, &rdu
, sizeof(rdu
));
324 case AUFS_CTL_RDU_INO
:
325 err
= au_rdu_ino(file
, &rdu
);
339 long au_rdu_compat_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
343 void __user
*p
= compat_ptr(arg
);
345 /* todo: get_user()? */
346 err
= copy_from_user(&rdu
, p
, sizeof(rdu
));
352 rdu
.ent
.e
= compat_ptr(rdu
.ent
.ul
);
353 err
= au_rdu_verify(&rdu
);
359 err
= au_rdu(file
, &rdu
);
363 rdu
.ent
.ul
= ptr_to_compat(rdu
.ent
.e
);
364 rdu
.tail
.ul
= ptr_to_compat(rdu
.tail
.e
);
365 e
= copy_to_user(p
, &rdu
, sizeof(rdu
));
371 case AUFS_CTL_RDU_INO
:
372 err
= au_rdu_ino(file
, &rdu
);