diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/vfs_file.c | 114 | ||||
| -rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
| -rw-r--r-- | fs/nfs_common/nfsacl.c | 70 |
3 files changed, 69 insertions, 117 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index a4799e971d1c..bbc3cc63854f 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -175,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | /** | 177 | /** |
| 178 | * v9fs_read - read from a file (internal) | 178 | * v9fs_file_read - read from a file |
| 179 | * @filep: file pointer to read | 179 | * @filep: file pointer to read |
| 180 | * @data: data buffer to read data into | 180 | * @data: data buffer to read data into |
| 181 | * @count: size of buffer | 181 | * @count: size of buffer |
| 182 | * @offset: offset at which to read data | 182 | * @offset: offset at which to read data |
| 183 | * | 183 | * |
| 184 | */ | 184 | */ |
| 185 | |||
| 186 | static ssize_t | 185 | static ssize_t |
| 187 | v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | 186 | v9fs_file_read(struct file *filp, char __user * data, size_t count, |
| 187 | loff_t * offset) | ||
| 188 | { | 188 | { |
| 189 | struct inode *inode = filp->f_dentry->d_inode; | 189 | struct inode *inode = filp->f_dentry->d_inode; |
| 190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
| @@ -194,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 194 | int rsize = 0; | 194 | int rsize = 0; |
| 195 | int result = 0; | 195 | int result = 0; |
| 196 | int total = 0; | 196 | int total = 0; |
| 197 | int n; | ||
| 197 | 198 | ||
| 198 | dprintk(DEBUG_VFS, "\n"); | 199 | dprintk(DEBUG_VFS, "\n"); |
| 199 | 200 | ||
| @@ -216,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 216 | } else | 217 | } else |
| 217 | *offset += result; | 218 | *offset += result; |
| 218 | 219 | ||
| 219 | /* XXX - extra copy */ | 220 | n = copy_to_user(data, fcall->params.rread.data, result); |
| 220 | memcpy(buffer, fcall->params.rread.data, result); | 221 | if (n) { |
| 222 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); | ||
| 223 | kfree(fcall); | ||
| 224 | return -EFAULT; | ||
| 225 | } | ||
| 226 | |||
| 221 | count -= result; | 227 | count -= result; |
| 222 | buffer += result; | 228 | data += result; |
| 223 | total += result; | 229 | total += result; |
| 224 | 230 | ||
| 225 | kfree(fcall); | 231 | kfree(fcall); |
| @@ -232,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 232 | } | 238 | } |
| 233 | 239 | ||
| 234 | /** | 240 | /** |
| 235 | * v9fs_file_read - read from a file | 241 | * v9fs_file_write - write to a file |
| 236 | * @filep: file pointer to read | ||
| 237 | * @data: data buffer to read data into | ||
| 238 | * @count: size of buffer | ||
| 239 | * @offset: offset at which to read data | ||
| 240 | * | ||
| 241 | */ | ||
| 242 | |||
| 243 | static ssize_t | ||
| 244 | v9fs_file_read(struct file *filp, char __user * data, size_t count, | ||
| 245 | loff_t * offset) | ||
| 246 | { | ||
| 247 | int retval = -1; | ||
| 248 | int ret = 0; | ||
| 249 | char *buffer; | ||
| 250 | |||
| 251 | buffer = kmalloc(count, GFP_KERNEL); | ||
| 252 | if (!buffer) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | retval = v9fs_read(filp, buffer, count, offset); | ||
| 256 | if (retval > 0) { | ||
| 257 | if ((ret = copy_to_user(data, buffer, retval)) != 0) { | ||
| 258 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", | ||
| 259 | ret); | ||
| 260 | retval = ret; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | kfree(buffer); | ||
| 265 | |||
| 266 | return retval; | ||
| 267 | } | ||
| 268 | |||
| 269 | /** | ||
| 270 | * v9fs_write - write to a file | ||
| 271 | * @filep: file pointer to write | 242 | * @filep: file pointer to write |
| 272 | * @data: data buffer to write data from | 243 | * @data: data buffer to write data from |
| 273 | * @count: size of buffer | 244 | * @count: size of buffer |
| @@ -276,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count, | |||
| 276 | */ | 247 | */ |
| 277 | 248 | ||
| 278 | static ssize_t | 249 | static ssize_t |
| 279 | v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | 250 | v9fs_file_write(struct file *filp, const char __user * data, |
| 251 | size_t count, loff_t * offset) | ||
| 280 | { | 252 | { |
| 281 | struct inode *inode = filp->f_dentry->d_inode; | 253 | struct inode *inode = filp->f_dentry->d_inode; |
| 282 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 254 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
| @@ -286,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 286 | int result = -EIO; | 258 | int result = -EIO; |
| 287 | int rsize = 0; | 259 | int rsize = 0; |
| 288 | int total = 0; | 260 | int total = 0; |
| 261 | char *buf; | ||
| 289 | 262 | ||
| 290 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count, | 263 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, |
| 291 | (int)*offset); | 264 | (int)*offset); |
| 292 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; | 265 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; |
| 293 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) | 266 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) |
| 294 | rsize = v9fid->iounit; | 267 | rsize = v9fid->iounit; |
| 295 | 268 | ||
| 296 | dump_data(buffer, count); | 269 | buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL); |
| 270 | if (!buf) | ||
| 271 | return -ENOMEM; | ||
| 297 | 272 | ||
| 298 | do { | 273 | do { |
| 299 | if (count < rsize) | 274 | if (count < rsize) |
| 300 | rsize = count; | 275 | rsize = count; |
| 301 | 276 | ||
| 302 | result = | 277 | result = copy_from_user(buf, data, rsize); |
| 303 | v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall); | 278 | if (result) { |
| 279 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
| 280 | kfree(buf); | ||
| 281 | return -EFAULT; | ||
| 282 | } | ||
| 283 | |||
| 284 | dump_data(buf, rsize); | ||
| 285 | result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall); | ||
| 304 | if (result < 0) { | 286 | if (result < 0) { |
| 305 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", | 287 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", |
| 306 | FCALL_ERROR(fcall), result); | 288 | FCALL_ERROR(fcall), result); |
| 307 | kfree(fcall); | 289 | kfree(fcall); |
| 290 | kfree(buf); | ||
| 308 | return result; | 291 | return result; |
| 309 | } else | 292 | } else |
| 310 | *offset += result; | 293 | *offset += result; |
| 311 | 294 | ||
| 312 | kfree(fcall); | 295 | kfree(fcall); |
| 296 | fcall = NULL; | ||
| 313 | 297 | ||
| 314 | if (result != rsize) { | 298 | if (result != rsize) { |
| 315 | eprintk(KERN_ERR, | 299 | eprintk(KERN_ERR, |
| @@ -319,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 319 | } | 303 | } |
| 320 | 304 | ||
| 321 | count -= result; | 305 | count -= result; |
| 322 | buffer += result; | 306 | data += result; |
| 323 | total += result; | 307 | total += result; |
| 324 | } while (count); | 308 | } while (count); |
| 325 | 309 | ||
| 310 | kfree(buf); | ||
| 326 | return total; | 311 | return total; |
| 327 | } | 312 | } |
| 328 | 313 | ||
| 329 | /** | ||
| 330 | * v9fs_file_write - write to a file | ||
| 331 | * @filep: file pointer to write | ||
| 332 | * @data: data buffer to write data from | ||
| 333 | * @count: size of buffer | ||
| 334 | * @offset: offset at which to write data | ||
| 335 | * | ||
| 336 | */ | ||
| 337 | |||
| 338 | static ssize_t | ||
| 339 | v9fs_file_write(struct file *filp, const char __user * data, | ||
| 340 | size_t count, loff_t * offset) | ||
| 341 | { | ||
| 342 | int ret = -1; | ||
| 343 | char *buffer; | ||
| 344 | |||
| 345 | buffer = kmalloc(count, GFP_KERNEL); | ||
| 346 | if (buffer == NULL) | ||
| 347 | return -ENOMEM; | ||
| 348 | |||
| 349 | ret = copy_from_user(buffer, data, count); | ||
| 350 | if (ret) { | ||
| 351 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
| 352 | ret = -EFAULT; | ||
| 353 | } else { | ||
| 354 | ret = v9fs_write(filp, buffer, count, offset); | ||
| 355 | } | ||
| 356 | |||
| 357 | kfree(buffer); | ||
| 358 | |||
| 359 | return ret; | ||
| 360 | } | ||
| 361 | |||
| 362 | struct file_operations v9fs_file_operations = { | 314 | struct file_operations v9fs_file_operations = { |
| 363 | .llseek = generic_file_llseek, | 315 | .llseek = generic_file_llseek, |
| 364 | .read = v9fs_file_read, | 316 | .read = v9fs_file_read, |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7976a238f0a3..d4b15576e584 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -905,7 +905,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
| 905 | send_sig(SIGKILL, current, 0); | 905 | send_sig(SIGKILL, current, 0); |
| 906 | goto out_free_dentry; | 906 | goto out_free_dentry; |
| 907 | } | 907 | } |
| 908 | if (padzero(elf_bss)) { | 908 | if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { |
| 909 | send_sig(SIGSEGV, current, 0); | 909 | send_sig(SIGSEGV, current, 0); |
| 910 | retval = -EFAULT; /* Nobody gets to see this, but.. */ | 910 | retval = -EFAULT; /* Nobody gets to see this, but.. */ |
| 911 | goto out_free_dentry; | 911 | goto out_free_dentry; |
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 251e5a1bb1c4..0c2be8c0307d 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c | |||
| @@ -48,43 +48,26 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | |||
| 48 | (struct nfsacl_encode_desc *) desc; | 48 | (struct nfsacl_encode_desc *) desc; |
| 49 | u32 *p = (u32 *) elem; | 49 | u32 *p = (u32 *) elem; |
| 50 | 50 | ||
| 51 | if (nfsacl_desc->count < nfsacl_desc->acl->a_count) { | 51 | struct posix_acl_entry *entry = |
| 52 | struct posix_acl_entry *entry = | 52 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; |
| 53 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; | ||
| 54 | 53 | ||
| 55 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); | 54 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); |
| 56 | switch(entry->e_tag) { | 55 | switch(entry->e_tag) { |
| 57 | case ACL_USER_OBJ: | 56 | case ACL_USER_OBJ: |
| 58 | *p++ = htonl(nfsacl_desc->uid); | 57 | *p++ = htonl(nfsacl_desc->uid); |
| 59 | break; | 58 | break; |
| 60 | case ACL_GROUP_OBJ: | 59 | case ACL_GROUP_OBJ: |
| 61 | *p++ = htonl(nfsacl_desc->gid); | 60 | *p++ = htonl(nfsacl_desc->gid); |
| 62 | break; | 61 | break; |
| 63 | case ACL_USER: | 62 | case ACL_USER: |
| 64 | case ACL_GROUP: | 63 | case ACL_GROUP: |
| 65 | *p++ = htonl(entry->e_id); | 64 | *p++ = htonl(entry->e_id); |
| 66 | break; | 65 | break; |
| 67 | default: /* Solaris depends on that! */ | 66 | default: /* Solaris depends on that! */ |
| 68 | *p++ = 0; | 67 | *p++ = 0; |
| 69 | break; | 68 | break; |
| 70 | } | ||
| 71 | *p++ = htonl(entry->e_perm & S_IRWXO); | ||
| 72 | } else { | ||
| 73 | const struct posix_acl_entry *pa, *pe; | ||
| 74 | int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE; | ||
| 75 | |||
| 76 | FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) { | ||
| 77 | if (pa->e_tag == ACL_GROUP_OBJ) { | ||
| 78 | group_obj_perm = pa->e_perm & S_IRWXO; | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | /* fake up ACL_MASK entry */ | ||
| 83 | *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag); | ||
| 84 | *p++ = htonl(0); | ||
| 85 | *p++ = htonl(group_obj_perm); | ||
| 86 | } | 69 | } |
| 87 | 70 | *p++ = htonl(entry->e_perm & S_IRWXO); | |
| 88 | return 0; | 71 | return 0; |
| 89 | } | 72 | } |
| 90 | 73 | ||
| @@ -105,11 +88,28 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
| 105 | .gid = inode->i_gid, | 88 | .gid = inode->i_gid, |
| 106 | }; | 89 | }; |
| 107 | int err; | 90 | int err; |
| 91 | struct posix_acl *acl2 = NULL; | ||
| 108 | 92 | ||
| 109 | if (entries > NFS_ACL_MAX_ENTRIES || | 93 | if (entries > NFS_ACL_MAX_ENTRIES || |
| 110 | xdr_encode_word(buf, base, entries)) | 94 | xdr_encode_word(buf, base, entries)) |
| 111 | return -EINVAL; | 95 | return -EINVAL; |
| 96 | if (encode_entries && acl && acl->a_count == 3) { | ||
| 97 | /* Fake up an ACL_MASK entry. */ | ||
| 98 | acl2 = posix_acl_alloc(4, GFP_KERNEL); | ||
| 99 | if (!acl2) | ||
| 100 | return -ENOMEM; | ||
| 101 | /* Insert entries in canonical order: other orders seem | ||
| 102 | to confuse Solaris VxFS. */ | ||
| 103 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ | ||
| 104 | acl2->a_entries[1] = acl->a_entries[1]; /* ACL_GROUP_OBJ */ | ||
| 105 | acl2->a_entries[2] = acl->a_entries[1]; /* ACL_MASK */ | ||
| 106 | acl2->a_entries[2].e_tag = ACL_MASK; | ||
| 107 | acl2->a_entries[3] = acl->a_entries[2]; /* ACL_OTHER */ | ||
| 108 | nfsacl_desc.acl = acl2; | ||
| 109 | } | ||
| 112 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); | 110 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); |
| 111 | if (acl2) | ||
| 112 | posix_acl_release(acl2); | ||
| 113 | if (!err) | 113 | if (!err) |
| 114 | err = 8 + nfsacl_desc.desc.elem_size * | 114 | err = 8 + nfsacl_desc.desc.elem_size * |
| 115 | nfsacl_desc.desc.array_len; | 115 | nfsacl_desc.desc.array_len; |
