1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* AFS filesystem symbolic link handling 3 * 4 * Copyright (C) 2026 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/fs.h> 10 #include <linux/namei.h> 11 #include <linux/pagemap.h> 12 #include <linux/iov_iter.h> 13 #include "internal.h" 14 15 static void afs_put_symlink(struct afs_symlink *symlink) 16 { 17 if (refcount_dec_and_test(&symlink->ref)) 18 kfree_rcu(symlink, rcu); 19 } 20 21 static void afs_replace_symlink(struct afs_vnode *vnode, struct afs_symlink *symlink) 22 { 23 struct afs_symlink *old; 24 25 old = rcu_replace_pointer(vnode->symlink, symlink, 26 lockdep_is_held(&vnode->validate_lock)); 27 if (old) 28 afs_put_symlink(old); 29 } 30 31 /* 32 * In the event that a third-party update of a symlink occurs, dispose of the 33 * copy of the old contents. Called under ->validate_lock. 34 */ 35 void afs_invalidate_symlink(struct afs_vnode *vnode) 36 { 37 afs_replace_symlink(vnode, NULL); 38 } 39 40 /* 41 * Dispose of a symlink copy during inode deletion. 42 */ 43 void afs_evict_symlink(struct afs_vnode *vnode) 44 { 45 struct afs_symlink *old; 46 47 old = rcu_replace_pointer(vnode->symlink, NULL, true); 48 if (old) 49 afs_put_symlink(old); 50 51 } 52 53 /* 54 * Set up a locally created symlink inode for immediate write to the cache. 55 */ 56 void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op) 57 { 58 struct afs_symlink *symlink = op->create.symlink; 59 size_t dsize = 0; 60 size_t size = strlen(symlink->content) + 1; 61 char *p; 62 63 rcu_assign_pointer(vnode->symlink, symlink); 64 op->create.symlink = NULL; 65 66 if (!fscache_cookie_enabled(netfs_i_cookie(&vnode->netfs))) 67 return; 68 69 if (netfs_alloc_folioq_buffer(NULL, &vnode->directory, &dsize, size, 70 mapping_gfp_mask(vnode->netfs.inode.i_mapping)) < 0) 71 return; 72 73 vnode->directory_size = dsize; 74 p = kmap_local_folio(folioq_folio(vnode->directory, 0), 0); 75 memcpy(p, symlink->content, size); 76 kunmap_local(p); 77 netfs_single_mark_inode_dirty(&vnode->netfs.inode); 78 } 79 80 /* 81 * Read a symlink in a single download. 82 */ 83 static ssize_t afs_do_read_symlink(struct afs_vnode *vnode) 84 { 85 struct afs_symlink *symlink; 86 struct iov_iter iter; 87 ssize_t ret; 88 loff_t i_size; 89 90 i_size = i_size_read(&vnode->netfs.inode); 91 if (i_size > PAGE_SIZE - 1) { 92 trace_afs_file_error(vnode, -EFBIG, afs_file_error_dir_big); 93 return -EFBIG; 94 } 95 96 if (!vnode->directory) { 97 size_t cur_size = 0; 98 99 ret = netfs_alloc_folioq_buffer(NULL, 100 &vnode->directory, &cur_size, PAGE_SIZE, 101 mapping_gfp_mask(vnode->netfs.inode.i_mapping)); 102 vnode->directory_size = PAGE_SIZE - 1; 103 if (ret < 0) 104 return ret; 105 } 106 107 iov_iter_folio_queue(&iter, ITER_DEST, vnode->directory, 0, 0, PAGE_SIZE); 108 109 /* AFS requires us to perform the read of a symlink as a single unit to 110 * avoid issues with the content being changed between reads. 111 */ 112 ret = netfs_read_single(&vnode->netfs.inode, NULL, &iter); 113 if (ret >= 0) { 114 i_size = ret; 115 if (i_size > PAGE_SIZE - 1) { 116 trace_afs_file_error(vnode, -EFBIG, afs_file_error_dir_big); 117 return -EFBIG; 118 } 119 vnode->directory_size = i_size; 120 121 /* Copy the symlink. */ 122 symlink = kmalloc_flex(struct afs_symlink, content, i_size + 1, 123 GFP_KERNEL); 124 if (!symlink) 125 return -ENOMEM; 126 127 refcount_set(&symlink->ref, 1); 128 symlink->content[i_size] = 0; 129 130 const char *s = kmap_local_folio(folioq_folio(vnode->directory, 0), 0); 131 132 memcpy(symlink->content, s, i_size); 133 kunmap_local(s); 134 135 afs_replace_symlink(vnode, symlink); 136 } 137 138 if (!fscache_cookie_enabled(netfs_i_cookie(&vnode->netfs))) { 139 netfs_free_folioq_buffer(vnode->directory); 140 vnode->directory = NULL; 141 vnode->directory_size = 0; 142 } 143 144 return ret; 145 } 146 147 static ssize_t afs_read_symlink(struct afs_vnode *vnode) 148 { 149 ssize_t ret; 150 151 fscache_use_cookie(afs_vnode_cache(vnode), false); 152 ret = afs_do_read_symlink(vnode); 153 fscache_unuse_cookie(afs_vnode_cache(vnode), NULL, NULL); 154 return ret; 155 } 156 157 static void afs_put_link(void *arg) 158 { 159 afs_put_symlink(arg); 160 } 161 162 const char *afs_get_link(struct dentry *dentry, struct inode *inode, 163 struct delayed_call *callback) 164 { 165 struct afs_symlink *symlink; 166 struct afs_vnode *vnode = AFS_FS_I(inode); 167 ssize_t ret; 168 169 if (!dentry) { 170 /* RCU pathwalk. */ 171 symlink = rcu_dereference(vnode->symlink); 172 if (!symlink || !afs_check_validity(vnode)) 173 return ERR_PTR(-ECHILD); 174 set_delayed_call(callback, NULL, NULL); 175 return symlink->content; 176 } 177 178 if (vnode->symlink) { 179 ret = afs_validate(vnode, NULL); 180 if (ret < 0) 181 return ERR_PTR(ret); 182 183 down_read(&vnode->validate_lock); 184 if (vnode->symlink) 185 goto good; 186 up_read(&vnode->validate_lock); 187 } 188 189 if (down_write_killable(&vnode->validate_lock) < 0) 190 return ERR_PTR(-ERESTARTSYS); 191 if (!vnode->symlink) { 192 ret = afs_read_symlink(vnode); 193 if (ret < 0) { 194 up_write(&vnode->validate_lock); 195 return ERR_PTR(ret); 196 } 197 } 198 199 downgrade_write(&vnode->validate_lock); 200 201 good: 202 symlink = rcu_dereference_protected(vnode->symlink, 203 lockdep_is_held(&vnode->validate_lock)); 204 refcount_inc(&symlink->ref); 205 up_read(&vnode->validate_lock); 206 207 set_delayed_call(callback, afs_put_link, symlink); 208 return symlink->content; 209 } 210 211 int afs_readlink(struct dentry *dentry, char __user *buffer, int buflen) 212 { 213 DEFINE_DELAYED_CALL(done); 214 const char *content; 215 int len; 216 217 content = afs_get_link(dentry, d_inode(dentry), &done); 218 if (IS_ERR(content)) { 219 do_delayed_call(&done); 220 return PTR_ERR(content); 221 } 222 223 len = umin(strlen(content), buflen); 224 if (copy_to_user(buffer, content, len)) 225 len = -EFAULT; 226 do_delayed_call(&done); 227 return len; 228 } 229 230 /* 231 * Write the symlink contents to the cache as a single blob. We then throw 232 * away the page we used to receive it. 233 */ 234 int afs_symlink_writepages(struct address_space *mapping, 235 struct writeback_control *wbc) 236 { 237 struct afs_vnode *vnode = AFS_FS_I(mapping->host); 238 struct iov_iter iter; 239 int ret = 0; 240 241 if (!down_read_trylock(&vnode->validate_lock)) { 242 if (wbc->sync_mode == WB_SYNC_NONE) { 243 /* The VFS will have undirtied the inode. */ 244 netfs_single_mark_inode_dirty(&vnode->netfs.inode); 245 return 0; 246 } 247 down_read(&vnode->validate_lock); 248 } 249 250 if (vnode->directory && 251 atomic64_read(&vnode->cb_expires_at) != AFS_NO_CB_PROMISE) { 252 iov_iter_folio_queue(&iter, ITER_SOURCE, vnode->directory, 0, 0, 253 i_size_read(&vnode->netfs.inode)); 254 ret = netfs_writeback_single(mapping, wbc, &iter); 255 } 256 257 if (ret == 0) { 258 mutex_lock(&vnode->netfs.wb_lock); 259 netfs_free_folioq_buffer(vnode->directory); 260 vnode->directory = NULL; 261 vnode->directory_size = 0; 262 mutex_unlock(&vnode->netfs.wb_lock); 263 } else if (ret == 1) { 264 ret = 0; /* Skipped write due to lock conflict. */ 265 } 266 267 up_read(&vnode->validate_lock); 268 return ret; 269 } 270 271 const struct inode_operations afs_symlink_inode_operations = { 272 .get_link = afs_get_link, 273 .readlink = afs_readlink, 274 }; 275 276 const struct address_space_operations afs_symlink_aops = { 277 .writepages = afs_symlink_writepages, 278 }; 279