diff options
author | Petr Vandrovec <petr@vandrovec.name> | 2010-09-26 19:47:33 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2010-10-04 15:10:52 -0400 |
commit | 2e54eb96e2c801f33d95b5dade15212ac4d6c4a5 (patch) | |
tree | c2996f29aa49881e93c7a37fad41e4961f6b8578 | |
parent | 60056794127a25d641465b706e8828186f7a2e1f (diff) |
BKL: Remove BKL from ncpfs
Dozen of changes in ncpfs to provide some locking other than BKL.
In readdir cache unlock and mark complete first page as last operation,
so it can be used for synchronization, as code intended.
When updating dentry name on case insensitive filesystems do at least
some basic locking...
Hold i_mutex when updating inode fields.
Push some ncp_conn_is_valid down to ncp_request. Connection can become
invalid at any moment, and fewer error code paths to test the better.
Use i_size_{read,write} to modify file size.
Set inode's backing_dev_info as ncpfs has its own special bdi.
In ioctl unbreak ioctls invoked on filesystem mounted 'ro' - tests are
for inode writeable or owner match, but were turned to filesystem
writeable and inode writeable or owner match. Also collect all permission
checks in single place.
Add some locking, and remove comments saying that it would be cool to
add some locks to the code.
Constify some pointers.
Signed-off-by: Petr Vandrovec <petr@vandrovec.name>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | fs/ncpfs/dir.c | 221 | ||||
-rw-r--r-- | fs/ncpfs/file.c | 25 | ||||
-rw-r--r-- | fs/ncpfs/inode.c | 41 | ||||
-rw-r--r-- | fs/ncpfs/ioctl.c | 470 | ||||
-rw-r--r-- | fs/ncpfs/ncplib_kernel.c | 101 | ||||
-rw-r--r-- | fs/ncpfs/ncplib_kernel.h | 15 | ||||
-rw-r--r-- | fs/ncpfs/ncpsign_kernel.c | 10 | ||||
-rw-r--r-- | fs/ncpfs/sock.c | 1 | ||||
-rw-r--r-- | include/linux/ncp_fs.h | 28 | ||||
-rw-r--r-- | include/linux/ncp_fs_sb.h | 4 |
10 files changed, 487 insertions, 429 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 9578cbe0cd58..aac8832e919e 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -95,6 +95,34 @@ const struct dentry_operations ncp_root_dentry_operations = | |||
95 | }; | 95 | }; |
96 | 96 | ||
97 | 97 | ||
98 | #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) | ||
99 | |||
100 | static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) | ||
101 | { | ||
102 | #ifdef CONFIG_NCPFS_SMALLDOS | ||
103 | int ns = ncp_namespace(i); | ||
104 | |||
105 | if ((ns == NW_NS_DOS) | ||
106 | #ifdef CONFIG_NCPFS_OS2_NS | ||
107 | || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) | ||
108 | #endif /* CONFIG_NCPFS_OS2_NS */ | ||
109 | ) | ||
110 | return 0; | ||
111 | #endif /* CONFIG_NCPFS_SMALLDOS */ | ||
112 | return 1; | ||
113 | } | ||
114 | |||
115 | #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) | ||
116 | |||
117 | static inline int ncp_case_sensitive(struct dentry *dentry) | ||
118 | { | ||
119 | #ifdef CONFIG_NCPFS_NFS_NS | ||
120 | return ncp_namespace(dentry->d_inode) == NW_NS_NFS; | ||
121 | #else | ||
122 | return 0; | ||
123 | #endif /* CONFIG_NCPFS_NFS_NS */ | ||
124 | } | ||
125 | |||
98 | /* | 126 | /* |
99 | * Note: leave the hash unchanged if the directory | 127 | * Note: leave the hash unchanged if the directory |
100 | * is case-sensitive. | 128 | * is case-sensitive. |
@@ -102,13 +130,12 @@ const struct dentry_operations ncp_root_dentry_operations = | |||
102 | static int | 130 | static int |
103 | ncp_hash_dentry(struct dentry *dentry, struct qstr *this) | 131 | ncp_hash_dentry(struct dentry *dentry, struct qstr *this) |
104 | { | 132 | { |
105 | struct nls_table *t; | 133 | if (!ncp_case_sensitive(dentry)) { |
106 | unsigned long hash; | 134 | struct nls_table *t; |
107 | int i; | 135 | unsigned long hash; |
108 | 136 | int i; | |
109 | t = NCP_IO_TABLE(dentry); | ||
110 | 137 | ||
111 | if (!ncp_case_sensitive(dentry->d_inode)) { | 138 | t = NCP_IO_TABLE(dentry); |
112 | hash = init_name_hash(); | 139 | hash = init_name_hash(); |
113 | for (i=0; i<this->len ; i++) | 140 | for (i=0; i<this->len ; i++) |
114 | hash = partial_name_hash(ncp_tolower(t, this->name[i]), | 141 | hash = partial_name_hash(ncp_tolower(t, this->name[i]), |
@@ -124,7 +151,7 @@ ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) | |||
124 | if (a->len != b->len) | 151 | if (a->len != b->len) |
125 | return 1; | 152 | return 1; |
126 | 153 | ||
127 | if (ncp_case_sensitive(dentry->d_inode)) | 154 | if (ncp_case_sensitive(dentry)) |
128 | return strncmp(a->name, b->name, a->len); | 155 | return strncmp(a->name, b->name, a->len); |
129 | 156 | ||
130 | return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); | 157 | return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); |
@@ -266,7 +293,7 @@ leave_me:; | |||
266 | 293 | ||
267 | 294 | ||
268 | static int | 295 | static int |
269 | __ncp_lookup_validate(struct dentry *dentry) | 296 | ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd) |
270 | { | 297 | { |
271 | struct ncp_server *server; | 298 | struct ncp_server *server; |
272 | struct dentry *parent; | 299 | struct dentry *parent; |
@@ -283,9 +310,6 @@ __ncp_lookup_validate(struct dentry *dentry) | |||
283 | 310 | ||
284 | server = NCP_SERVER(dir); | 311 | server = NCP_SERVER(dir); |
285 | 312 | ||
286 | if (!ncp_conn_valid(server)) | ||
287 | goto finished; | ||
288 | |||
289 | /* | 313 | /* |
290 | * Inspired by smbfs: | 314 | * Inspired by smbfs: |
291 | * The default validation is based on dentry age: | 315 | * The default validation is based on dentry age: |
@@ -304,8 +328,11 @@ __ncp_lookup_validate(struct dentry *dentry) | |||
304 | if (ncp_is_server_root(dir)) { | 328 | if (ncp_is_server_root(dir)) { |
305 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 329 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
306 | dentry->d_name.len, 1); | 330 | dentry->d_name.len, 1); |
307 | if (!res) | 331 | if (!res) { |
308 | res = ncp_lookup_volume(server, __name, &(finfo.i)); | 332 | res = ncp_lookup_volume(server, __name, &(finfo.i)); |
333 | if (!res) | ||
334 | ncp_update_known_namespace(server, finfo.i.volNumber, NULL); | ||
335 | } | ||
309 | } else { | 336 | } else { |
310 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 337 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
311 | dentry->d_name.len, !ncp_preserve_case(dir)); | 338 | dentry->d_name.len, !ncp_preserve_case(dir)); |
@@ -320,13 +347,17 @@ __ncp_lookup_validate(struct dentry *dentry) | |||
320 | * what we remember, it's not valid any more. | 347 | * what we remember, it's not valid any more. |
321 | */ | 348 | */ |
322 | if (!res) { | 349 | if (!res) { |
323 | if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) { | 350 | struct inode *inode = dentry->d_inode; |
351 | |||
352 | mutex_lock(&inode->i_mutex); | ||
353 | if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) { | ||
324 | ncp_new_dentry(dentry); | 354 | ncp_new_dentry(dentry); |
325 | val=1; | 355 | val=1; |
326 | } else | 356 | } else |
327 | DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); | 357 | DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); |
328 | 358 | ||
329 | ncp_update_inode2(dentry->d_inode, &finfo); | 359 | ncp_update_inode2(inode, &finfo); |
360 | mutex_unlock(&inode->i_mutex); | ||
330 | } | 361 | } |
331 | 362 | ||
332 | finished: | 363 | finished: |
@@ -335,16 +366,6 @@ finished: | |||
335 | return val; | 366 | return val; |
336 | } | 367 | } |
337 | 368 | ||
338 | static int | ||
339 | ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd) | ||
340 | { | ||
341 | int res; | ||
342 | lock_kernel(); | ||
343 | res = __ncp_lookup_validate(dentry); | ||
344 | unlock_kernel(); | ||
345 | return res; | ||
346 | } | ||
347 | |||
348 | static struct dentry * | 369 | static struct dentry * |
349 | ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) | 370 | ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) |
350 | { | 371 | { |
@@ -411,8 +432,6 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
411 | int result, mtime_valid = 0; | 432 | int result, mtime_valid = 0; |
412 | time_t mtime = 0; | 433 | time_t mtime = 0; |
413 | 434 | ||
414 | lock_kernel(); | ||
415 | |||
416 | ctl.page = NULL; | 435 | ctl.page = NULL; |
417 | ctl.cache = NULL; | 436 | ctl.cache = NULL; |
418 | 437 | ||
@@ -421,6 +440,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
421 | (int) filp->f_pos); | 440 | (int) filp->f_pos); |
422 | 441 | ||
423 | result = -EIO; | 442 | result = -EIO; |
443 | /* Do not generate '.' and '..' when server is dead. */ | ||
424 | if (!ncp_conn_valid(server)) | 444 | if (!ncp_conn_valid(server)) |
425 | goto out; | 445 | goto out; |
426 | 446 | ||
@@ -532,6 +552,12 @@ read_really: | |||
532 | ctl.head.end = ctl.fpos - 1; | 552 | ctl.head.end = ctl.fpos - 1; |
533 | ctl.head.eof = ctl.valid; | 553 | ctl.head.eof = ctl.valid; |
534 | finished: | 554 | finished: |
555 | if (ctl.page) { | ||
556 | kunmap(ctl.page); | ||
557 | SetPageUptodate(ctl.page); | ||
558 | unlock_page(ctl.page); | ||
559 | page_cache_release(ctl.page); | ||
560 | } | ||
535 | if (page) { | 561 | if (page) { |
536 | cache->head = ctl.head; | 562 | cache->head = ctl.head; |
537 | kunmap(page); | 563 | kunmap(page); |
@@ -539,23 +565,17 @@ finished: | |||
539 | unlock_page(page); | 565 | unlock_page(page); |
540 | page_cache_release(page); | 566 | page_cache_release(page); |
541 | } | 567 | } |
542 | if (ctl.page) { | ||
543 | kunmap(ctl.page); | ||
544 | SetPageUptodate(ctl.page); | ||
545 | unlock_page(ctl.page); | ||
546 | page_cache_release(ctl.page); | ||
547 | } | ||
548 | out: | 568 | out: |
549 | unlock_kernel(); | ||
550 | return result; | 569 | return result; |
551 | } | 570 | } |
552 | 571 | ||
553 | static int | 572 | static int |
554 | ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 573 | ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
555 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry) | 574 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, |
575 | int inval_childs) | ||
556 | { | 576 | { |
557 | struct dentry *newdent, *dentry = filp->f_path.dentry; | 577 | struct dentry *newdent, *dentry = filp->f_path.dentry; |
558 | struct inode *newino, *inode = dentry->d_inode; | 578 | struct inode *dir = dentry->d_inode; |
559 | struct ncp_cache_control ctl = *ctrl; | 579 | struct ncp_cache_control ctl = *ctrl; |
560 | struct qstr qname; | 580 | struct qstr qname; |
561 | int valid = 0; | 581 | int valid = 0; |
@@ -564,9 +584,9 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
564 | __u8 __name[NCP_MAXPATHLEN + 1]; | 584 | __u8 __name[NCP_MAXPATHLEN + 1]; |
565 | 585 | ||
566 | qname.len = sizeof(__name); | 586 | qname.len = sizeof(__name); |
567 | if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len, | 587 | if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len, |
568 | entry->i.entryName, entry->i.nameLen, | 588 | entry->i.entryName, entry->i.nameLen, |
569 | !ncp_preserve_entry_case(inode, entry->i.NSCreator))) | 589 | !ncp_preserve_entry_case(dir, entry->i.NSCreator))) |
570 | return 1; /* I'm not sure */ | 590 | return 1; /* I'm not sure */ |
571 | 591 | ||
572 | qname.name = __name; | 592 | qname.name = __name; |
@@ -584,22 +604,64 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
584 | goto end_advance; | 604 | goto end_advance; |
585 | } else { | 605 | } else { |
586 | hashed = 1; | 606 | hashed = 1; |
587 | memcpy((char *) newdent->d_name.name, qname.name, | 607 | |
588 | newdent->d_name.len); | 608 | /* If case sensitivity changed for this volume, all entries below this one |
609 | should be thrown away. This entry itself is not affected, as its case | ||
610 | sensitivity is controlled by its own parent. */ | ||
611 | if (inval_childs) | ||
612 | shrink_dcache_parent(newdent); | ||
613 | |||
614 | /* | ||
615 | * It is not as dangerous as it looks. NetWare's OS2 namespace is | ||
616 | * case preserving yet case insensitive. So we update dentry's name | ||
617 | * as received from server. We found dentry via d_lookup with our | ||
618 | * hash, so we know that hash does not change, and so replacing name | ||
619 | * should be reasonably safe. | ||
620 | */ | ||
621 | if (qname.len == newdent->d_name.len && | ||
622 | memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) { | ||
623 | struct inode *inode = newdent->d_inode; | ||
624 | |||
625 | /* | ||
626 | * Inside ncpfs all uses of d_name are either for debugging, | ||
627 | * or on functions which acquire inode mutex (mknod, creat, | ||
628 | * lookup). So grab i_mutex here, to be sure. d_path | ||
629 | * uses dcache_lock when generating path, so we should too. | ||
630 | * And finally d_compare is protected by dentry's d_lock, so | ||
631 | * here we go. | ||
632 | */ | ||
633 | if (inode) | ||
634 | mutex_lock(&inode->i_mutex); | ||
635 | spin_lock(&dcache_lock); | ||
636 | spin_lock(&newdent->d_lock); | ||
637 | memcpy((char *) newdent->d_name.name, qname.name, | ||
638 | newdent->d_name.len); | ||
639 | spin_unlock(&newdent->d_lock); | ||
640 | spin_unlock(&dcache_lock); | ||
641 | if (inode) | ||
642 | mutex_unlock(&inode->i_mutex); | ||
643 | } | ||
589 | } | 644 | } |
590 | 645 | ||
591 | if (!newdent->d_inode) { | 646 | if (!newdent->d_inode) { |
647 | struct inode *inode; | ||
648 | |||
592 | entry->opened = 0; | 649 | entry->opened = 0; |
593 | entry->ino = iunique(inode->i_sb, 2); | 650 | entry->ino = iunique(dir->i_sb, 2); |
594 | newino = ncp_iget(inode->i_sb, entry); | 651 | inode = ncp_iget(dir->i_sb, entry); |
595 | if (newino) { | 652 | if (inode) { |
596 | newdent->d_op = &ncp_dentry_operations; | 653 | newdent->d_op = &ncp_dentry_operations; |
597 | d_instantiate(newdent, newino); | 654 | d_instantiate(newdent, inode); |
598 | if (!hashed) | 655 | if (!hashed) |
599 | d_rehash(newdent); | 656 | d_rehash(newdent); |
600 | } | 657 | } |
601 | } else | 658 | } else { |
602 | ncp_update_inode2(newdent->d_inode, entry); | 659 | struct inode *inode = newdent->d_inode; |
660 | |||
661 | mutex_lock(&inode->i_mutex); | ||
662 | ncp_update_inode2(inode, entry); | ||
663 | mutex_unlock(&inode->i_mutex); | ||
664 | } | ||
603 | 665 | ||
604 | if (newdent->d_inode) { | 666 | if (newdent->d_inode) { |
605 | ino = newdent->d_inode->i_ino; | 667 | ino = newdent->d_inode->i_ino; |
@@ -617,7 +679,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
617 | ctl.cache = NULL; | 679 | ctl.cache = NULL; |
618 | ctl.idx -= NCP_DIRCACHE_SIZE; | 680 | ctl.idx -= NCP_DIRCACHE_SIZE; |
619 | ctl.ofs += 1; | 681 | ctl.ofs += 1; |
620 | ctl.page = grab_cache_page(&inode->i_data, ctl.ofs); | 682 | ctl.page = grab_cache_page(&dir->i_data, ctl.ofs); |
621 | if (ctl.page) | 683 | if (ctl.page) |
622 | ctl.cache = kmap(ctl.page); | 684 | ctl.cache = kmap(ctl.page); |
623 | } | 685 | } |
@@ -633,7 +695,7 @@ end_advance: | |||
633 | if (!ino) | 695 | if (!ino) |
634 | ino = find_inode_number(dentry, &qname); | 696 | ino = find_inode_number(dentry, &qname); |
635 | if (!ino) | 697 | if (!ino) |
636 | ino = iunique(inode->i_sb, 2); | 698 | ino = iunique(dir->i_sb, 2); |
637 | ctl.filled = filldir(dirent, qname.name, qname.len, | 699 | ctl.filled = filldir(dirent, qname.name, qname.len, |
638 | filp->f_pos, ino, DT_UNKNOWN); | 700 | filp->f_pos, ino, DT_UNKNOWN); |
639 | if (!ctl.filled) | 701 | if (!ctl.filled) |
@@ -660,6 +722,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | |||
660 | (unsigned long) filp->f_pos); | 722 | (unsigned long) filp->f_pos); |
661 | 723 | ||
662 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { | 724 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { |
725 | int inval_dentry; | ||
663 | 726 | ||
664 | if (ncp_get_volume_info_with_number(server, i, &info) != 0) | 727 | if (ncp_get_volume_info_with_number(server, i, &info) != 0) |
665 | return; | 728 | return; |
@@ -675,8 +738,9 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | |||
675 | info.volume_name); | 738 | info.volume_name); |
676 | continue; | 739 | continue; |
677 | } | 740 | } |
741 | inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); | ||
678 | entry.volume = entry.i.volNumber; | 742 | entry.volume = entry.i.volNumber; |
679 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) | 743 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry)) |
680 | return; | 744 | return; |
681 | } | 745 | } |
682 | } | 746 | } |
@@ -739,7 +803,7 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, | |||
739 | rpl += onerpl; | 803 | rpl += onerpl; |
740 | rpls -= onerpl; | 804 | rpls -= onerpl; |
741 | entry.volume = entry.i.volNumber; | 805 | entry.volume = entry.i.volNumber; |
742 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) | 806 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0)) |
743 | break; | 807 | break; |
744 | } | 808 | } |
745 | } while (more); | 809 | } while (more); |
@@ -775,17 +839,19 @@ int ncp_conn_logged_in(struct super_block *sb) | |||
775 | if (dent) { | 839 | if (dent) { |
776 | struct inode* ino = dent->d_inode; | 840 | struct inode* ino = dent->d_inode; |
777 | if (ino) { | 841 | if (ino) { |
842 | ncp_update_known_namespace(server, volNumber, NULL); | ||
778 | NCP_FINFO(ino)->volNumber = volNumber; | 843 | NCP_FINFO(ino)->volNumber = volNumber; |
779 | NCP_FINFO(ino)->dirEntNum = dirEntNum; | 844 | NCP_FINFO(ino)->dirEntNum = dirEntNum; |
780 | NCP_FINFO(ino)->DosDirNum = DosDirNum; | 845 | NCP_FINFO(ino)->DosDirNum = DosDirNum; |
846 | result = 0; | ||
781 | } else { | 847 | } else { |
782 | DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); | 848 | DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); |
783 | } | 849 | } |
784 | } else { | 850 | } else { |
785 | DPRINTK("ncpfs: sb->s_root == NULL!\n"); | 851 | DPRINTK("ncpfs: sb->s_root == NULL!\n"); |
786 | } | 852 | } |
787 | } | 853 | } else |
788 | result = 0; | 854 | result = 0; |
789 | 855 | ||
790 | out: | 856 | out: |
791 | return result; | 857 | return result; |
@@ -799,7 +865,6 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc | |||
799 | int error, res, len; | 865 | int error, res, len; |
800 | __u8 __name[NCP_MAXPATHLEN + 1]; | 866 | __u8 __name[NCP_MAXPATHLEN + 1]; |
801 | 867 | ||
802 | lock_kernel(); | ||
803 | error = -EIO; | 868 | error = -EIO; |
804 | if (!ncp_conn_valid(server)) | 869 | if (!ncp_conn_valid(server)) |
805 | goto finished; | 870 | goto finished; |
@@ -813,6 +878,8 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc | |||
813 | dentry->d_name.len, 1); | 878 | dentry->d_name.len, 1); |
814 | if (!res) | 879 | if (!res) |
815 | res = ncp_lookup_volume(server, __name, &(finfo.i)); | 880 | res = ncp_lookup_volume(server, __name, &(finfo.i)); |
881 | if (!res) | ||
882 | ncp_update_known_namespace(server, finfo.i.volNumber, NULL); | ||
816 | } else { | 883 | } else { |
817 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 884 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
818 | dentry->d_name.len, !ncp_preserve_case(dir)); | 885 | dentry->d_name.len, !ncp_preserve_case(dir)); |
@@ -846,7 +913,6 @@ add_entry: | |||
846 | 913 | ||
847 | finished: | 914 | finished: |
848 | PPRINTK("ncp_lookup: result=%d\n", error); | 915 | PPRINTK("ncp_lookup: result=%d\n", error); |
849 | unlock_kernel(); | ||
850 | return ERR_PTR(error); | 916 | return ERR_PTR(error); |
851 | } | 917 | } |
852 | 918 | ||
@@ -887,11 +953,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, | |||
887 | PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n", | 953 | PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n", |
888 | dentry->d_parent->d_name.name, dentry->d_name.name, mode); | 954 | dentry->d_parent->d_name.name, dentry->d_name.name, mode); |
889 | 955 | ||
890 | error = -EIO; | ||
891 | lock_kernel(); | ||
892 | if (!ncp_conn_valid(server)) | ||
893 | goto out; | ||
894 | |||
895 | ncp_age_dentry(server, dentry); | 956 | ncp_age_dentry(server, dentry); |
896 | len = sizeof(__name); | 957 | len = sizeof(__name); |
897 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 958 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
@@ -917,6 +978,8 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, | |||
917 | if (result) { | 978 | if (result) { |
918 | if (result == 0x87) | 979 | if (result == 0x87) |
919 | error = -ENAMETOOLONG; | 980 | error = -ENAMETOOLONG; |
981 | else if (result < 0) | ||
982 | error = result; | ||
920 | DPRINTK("ncp_create: %s/%s failed\n", | 983 | DPRINTK("ncp_create: %s/%s failed\n", |
921 | dentry->d_parent->d_name.name, dentry->d_name.name); | 984 | dentry->d_parent->d_name.name, dentry->d_name.name); |
922 | goto out; | 985 | goto out; |
@@ -935,7 +998,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, | |||
935 | 998 | ||
936 | error = ncp_instantiate(dir, dentry, &finfo); | 999 | error = ncp_instantiate(dir, dentry, &finfo); |
937 | out: | 1000 | out: |
938 | unlock_kernel(); | ||
939 | return error; | 1001 | return error; |
940 | } | 1002 | } |
941 | 1003 | ||
@@ -955,11 +1017,6 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
955 | DPRINTK("ncp_mkdir: making %s/%s\n", | 1017 | DPRINTK("ncp_mkdir: making %s/%s\n", |
956 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1018 | dentry->d_parent->d_name.name, dentry->d_name.name); |
957 | 1019 | ||
958 | error = -EIO; | ||
959 | lock_kernel(); | ||
960 | if (!ncp_conn_valid(server)) | ||
961 | goto out; | ||
962 | |||
963 | ncp_age_dentry(server, dentry); | 1020 | ncp_age_dentry(server, dentry); |
964 | len = sizeof(__name); | 1021 | len = sizeof(__name); |
965 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 1022 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
@@ -967,12 +1024,11 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
967 | if (error) | 1024 | if (error) |
968 | goto out; | 1025 | goto out; |
969 | 1026 | ||
970 | error = -EACCES; | 1027 | error = ncp_open_create_file_or_subdir(server, dir, __name, |
971 | if (ncp_open_create_file_or_subdir(server, dir, __name, | ||
972 | OC_MODE_CREATE, aDIR, | 1028 | OC_MODE_CREATE, aDIR, |
973 | cpu_to_le16(0xffff), | 1029 | cpu_to_le16(0xffff), |
974 | &finfo) == 0) | 1030 | &finfo); |
975 | { | 1031 | if (error == 0) { |
976 | if (ncp_is_nfs_extras(server, finfo.volume)) { | 1032 | if (ncp_is_nfs_extras(server, finfo.volume)) { |
977 | mode |= S_IFDIR; | 1033 | mode |= S_IFDIR; |
978 | finfo.i.nfs.mode = mode; | 1034 | finfo.i.nfs.mode = mode; |
@@ -983,9 +1039,10 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
983 | goto out; | 1039 | goto out; |
984 | } | 1040 | } |
985 | error = ncp_instantiate(dir, dentry, &finfo); | 1041 | error = ncp_instantiate(dir, dentry, &finfo); |
1042 | } else if (error > 0) { | ||
1043 | error = -EACCES; | ||
986 | } | 1044 | } |
987 | out: | 1045 | out: |
988 | unlock_kernel(); | ||
989 | return error; | 1046 | return error; |
990 | } | 1047 | } |
991 | 1048 | ||
@@ -998,11 +1055,6 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) | |||
998 | DPRINTK("ncp_rmdir: removing %s/%s\n", | 1055 | DPRINTK("ncp_rmdir: removing %s/%s\n", |
999 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1056 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1000 | 1057 | ||
1001 | error = -EIO; | ||
1002 | lock_kernel(); | ||
1003 | if (!ncp_conn_valid(server)) | ||
1004 | goto out; | ||
1005 | |||
1006 | error = -EBUSY; | 1058 | error = -EBUSY; |
1007 | if (!d_unhashed(dentry)) | 1059 | if (!d_unhashed(dentry)) |
1008 | goto out; | 1060 | goto out; |
@@ -1036,11 +1088,10 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) | |||
1036 | error = -ENOENT; | 1088 | error = -ENOENT; |
1037 | break; | 1089 | break; |
1038 | default: | 1090 | default: |
1039 | error = -EACCES; | 1091 | error = result < 0 ? result : -EACCES; |
1040 | break; | 1092 | break; |
1041 | } | 1093 | } |
1042 | out: | 1094 | out: |
1043 | unlock_kernel(); | ||
1044 | return error; | 1095 | return error; |
1045 | } | 1096 | } |
1046 | 1097 | ||
@@ -1050,15 +1101,10 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) | |||
1050 | struct ncp_server *server; | 1101 | struct ncp_server *server; |
1051 | int error; | 1102 | int error; |
1052 | 1103 | ||
1053 | lock_kernel(); | ||
1054 | server = NCP_SERVER(dir); | 1104 | server = NCP_SERVER(dir); |
1055 | DPRINTK("ncp_unlink: unlinking %s/%s\n", | 1105 | DPRINTK("ncp_unlink: unlinking %s/%s\n", |
1056 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1106 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1057 | 1107 | ||
1058 | error = -EIO; | ||
1059 | if (!ncp_conn_valid(server)) | ||
1060 | goto out; | ||
1061 | |||
1062 | /* | 1108 | /* |
1063 | * Check whether to close the file ... | 1109 | * Check whether to close the file ... |
1064 | */ | 1110 | */ |
@@ -1097,12 +1143,9 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) | |||
1097 | error = -ENOENT; | 1143 | error = -ENOENT; |
1098 | break; | 1144 | break; |
1099 | default: | 1145 | default: |
1100 | error = -EACCES; | 1146 | error = error < 0 ? error : -EACCES; |
1101 | break; | 1147 | break; |
1102 | } | 1148 | } |
1103 | |||
1104 | out: | ||
1105 | unlock_kernel(); | ||
1106 | return error; | 1149 | return error; |
1107 | } | 1150 | } |
1108 | 1151 | ||
@@ -1118,11 +1161,6 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1118 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1161 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1119 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name); | 1162 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name); |
1120 | 1163 | ||
1121 | error = -EIO; | ||
1122 | lock_kernel(); | ||
1123 | if (!ncp_conn_valid(server)) | ||
1124 | goto out; | ||
1125 | |||
1126 | ncp_age_dentry(server, old_dentry); | 1164 | ncp_age_dentry(server, old_dentry); |
1127 | ncp_age_dentry(server, new_dentry); | 1165 | ncp_age_dentry(server, new_dentry); |
1128 | 1166 | ||
@@ -1161,11 +1199,10 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1161 | error = -ENOENT; | 1199 | error = -ENOENT; |
1162 | break; | 1200 | break; |
1163 | default: | 1201 | default: |
1164 | error = -EACCES; | 1202 | error = error < 0 ? error : -EACCES; |
1165 | break; | 1203 | break; |
1166 | } | 1204 | } |
1167 | out: | 1205 | out: |
1168 | unlock_kernel(); | ||
1169 | return error; | 1206 | return error; |
1170 | } | 1207 | } |
1171 | 1208 | ||
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 3639cc5cbdae..6c754f70c529 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
@@ -113,9 +113,6 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
113 | DPRINTK("ncp_file_read: enter %s/%s\n", | 113 | DPRINTK("ncp_file_read: enter %s/%s\n", |
114 | dentry->d_parent->d_name.name, dentry->d_name.name); | 114 | dentry->d_parent->d_name.name, dentry->d_name.name); |
115 | 115 | ||
116 | if (!ncp_conn_valid(NCP_SERVER(inode))) | ||
117 | return -EIO; | ||
118 | |||
119 | pos = *ppos; | 116 | pos = *ppos; |
120 | 117 | ||
121 | if ((ssize_t) count < 0) { | 118 | if ((ssize_t) count < 0) { |
@@ -192,13 +189,11 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
192 | 189 | ||
193 | DPRINTK("ncp_file_write: enter %s/%s\n", | 190 | DPRINTK("ncp_file_write: enter %s/%s\n", |
194 | dentry->d_parent->d_name.name, dentry->d_name.name); | 191 | dentry->d_parent->d_name.name, dentry->d_name.name); |
195 | if (!ncp_conn_valid(NCP_SERVER(inode))) | ||
196 | return -EIO; | ||
197 | if ((ssize_t) count < 0) | 192 | if ((ssize_t) count < 0) |
198 | return -EINVAL; | 193 | return -EINVAL; |
199 | pos = *ppos; | 194 | pos = *ppos; |
200 | if (file->f_flags & O_APPEND) { | 195 | if (file->f_flags & O_APPEND) { |
201 | pos = inode->i_size; | 196 | pos = i_size_read(inode); |
202 | } | 197 | } |
203 | 198 | ||
204 | if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { | 199 | if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { |
@@ -264,8 +259,11 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
264 | 259 | ||
265 | *ppos = pos; | 260 | *ppos = pos; |
266 | 261 | ||
267 | if (pos > inode->i_size) { | 262 | if (pos > i_size_read(inode)) { |
268 | inode->i_size = pos; | 263 | mutex_lock(&inode->i_mutex); |
264 | if (pos > i_size_read(inode)) | ||
265 | i_size_write(inode, pos); | ||
266 | mutex_unlock(&inode->i_mutex); | ||
269 | } | 267 | } |
270 | DPRINTK("ncp_file_write: exit %s/%s\n", | 268 | DPRINTK("ncp_file_write: exit %s/%s\n", |
271 | dentry->d_parent->d_name.name, dentry->d_name.name); | 269 | dentry->d_parent->d_name.name, dentry->d_name.name); |
@@ -281,18 +279,9 @@ static int ncp_release(struct inode *inode, struct file *file) { | |||
281 | return 0; | 279 | return 0; |
282 | } | 280 | } |
283 | 281 | ||
284 | static loff_t ncp_remote_llseek(struct file *file, loff_t offset, int origin) | ||
285 | { | ||
286 | loff_t ret; | ||
287 | lock_kernel(); | ||
288 | ret = generic_file_llseek_unlocked(file, offset, origin); | ||
289 | unlock_kernel(); | ||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | const struct file_operations ncp_file_operations = | 282 | const struct file_operations ncp_file_operations = |
294 | { | 283 | { |
295 | .llseek = ncp_remote_llseek, | 284 | .llseek = generic_file_llseek, |
296 | .read = ncp_file_read, | 285 | .read = ncp_file_read, |
297 | .write = ncp_file_write, | 286 | .write = ncp_file_write, |
298 | .unlocked_ioctl = ncp_ioctl, | 287 | .unlocked_ioctl = ncp_ioctl, |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index b4de38cf49f5..5f4e58d93fdd 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -139,7 +139,7 @@ static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) | |||
139 | inode->i_mode = nwi->nfs.mode; | 139 | inode->i_mode = nwi->nfs.mode; |
140 | } | 140 | } |
141 | 141 | ||
142 | inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; | 142 | inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; |
143 | 143 | ||
144 | inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); | 144 | inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); |
145 | inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); | 145 | inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); |
@@ -158,18 +158,21 @@ static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) | |||
158 | inode->i_mode = server->m.dir_mode; | 158 | inode->i_mode = server->m.dir_mode; |
159 | /* for directories dataStreamSize seems to be some | 159 | /* for directories dataStreamSize seems to be some |
160 | Object ID ??? */ | 160 | Object ID ??? */ |
161 | inode->i_size = NCP_BLOCK_SIZE; | 161 | i_size_write(inode, NCP_BLOCK_SIZE); |
162 | } else { | 162 | } else { |
163 | u32 size; | ||
164 | |||
163 | inode->i_mode = server->m.file_mode; | 165 | inode->i_mode = server->m.file_mode; |
164 | inode->i_size = le32_to_cpu(nwi->dataStreamSize); | 166 | size = le32_to_cpu(nwi->dataStreamSize); |
167 | i_size_write(inode, size); | ||
165 | #ifdef CONFIG_NCPFS_EXTRAS | 168 | #ifdef CONFIG_NCPFS_EXTRAS |
166 | if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) | 169 | if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) |
167 | && (nwi->attributes & aSHARED)) { | 170 | && (nwi->attributes & aSHARED)) { |
168 | switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { | 171 | switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { |
169 | case aHIDDEN: | 172 | case aHIDDEN: |
170 | if (server->m.flags & NCP_MOUNT_SYMLINKS) { | 173 | if (server->m.flags & NCP_MOUNT_SYMLINKS) { |
171 | if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE) | 174 | if (/* (size >= NCP_MIN_SYMLINK_SIZE) |
172 | && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) { | 175 | && */ (size <= NCP_MAX_SYMLINK_SIZE)) { |
173 | inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; | 176 | inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; |
174 | NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; | 177 | NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; |
175 | break; | 178 | break; |
@@ -208,7 +211,7 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) | |||
208 | } | 211 | } |
209 | 212 | ||
210 | /* | 213 | /* |
211 | * Fill in the inode based on the ncp_entry_info structure. | 214 | * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes. |
212 | */ | 215 | */ |
213 | static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) | 216 | static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) |
214 | { | 217 | { |
@@ -254,6 +257,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) | |||
254 | if (inode) { | 257 | if (inode) { |
255 | atomic_set(&NCP_FINFO(inode)->opened, info->opened); | 258 | atomic_set(&NCP_FINFO(inode)->opened, info->opened); |
256 | 259 | ||
260 | inode->i_mapping->backing_dev_info = sb->s_bdi; | ||
257 | inode->i_ino = info->ino; | 261 | inode->i_ino = info->ino; |
258 | ncp_set_attr(inode, info); | 262 | ncp_set_attr(inode, info); |
259 | if (S_ISREG(inode->i_mode)) { | 263 | if (S_ISREG(inode->i_mode)) { |
@@ -565,10 +569,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
565 | /* server->conn_status = 0; */ | 569 | /* server->conn_status = 0; */ |
566 | /* server->root_dentry = NULL; */ | 570 | /* server->root_dentry = NULL; */ |
567 | /* server->root_setuped = 0; */ | 571 | /* server->root_setuped = 0; */ |
572 | mutex_init(&server->root_setup_lock); | ||
568 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 573 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
569 | /* server->sign_wanted = 0; */ | 574 | /* server->sign_wanted = 0; */ |
570 | /* server->sign_active = 0; */ | 575 | /* server->sign_active = 0; */ |
571 | #endif | 576 | #endif |
577 | init_rwsem(&server->auth_rwsem); | ||
572 | server->auth.auth_type = NCP_AUTH_NONE; | 578 | server->auth.auth_type = NCP_AUTH_NONE; |
573 | /* server->auth.object_name_len = 0; */ | 579 | /* server->auth.object_name_len = 0; */ |
574 | /* server->auth.object_name = NULL; */ | 580 | /* server->auth.object_name = NULL; */ |
@@ -593,7 +599,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
593 | server->nls_io = load_nls_default(); | 599 | server->nls_io = load_nls_default(); |
594 | #endif /* CONFIG_NCPFS_NLS */ | 600 | #endif /* CONFIG_NCPFS_NLS */ |
595 | 601 | ||
596 | server->dentry_ttl = 0; /* no caching */ | 602 | atomic_set(&server->dentry_ttl, 0); /* no caching */ |
597 | 603 | ||
598 | INIT_LIST_HEAD(&server->tx.requests); | 604 | INIT_LIST_HEAD(&server->tx.requests); |
599 | mutex_init(&server->rcv.creq_mutex); | 605 | mutex_init(&server->rcv.creq_mutex); |
@@ -658,8 +664,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
658 | goto out_disconnect; | 664 | goto out_disconnect; |
659 | } | 665 | } |
660 | } | 666 | } |
667 | ncp_lock_server(server); | ||
661 | if (options & 2) | 668 | if (options & 2) |
662 | server->sign_wanted = 1; | 669 | server->sign_wanted = 1; |
670 | ncp_unlock_server(server); | ||
663 | } | 671 | } |
664 | else | 672 | else |
665 | #endif /* CONFIG_NCPFS_PACKET_SIGNING */ | 673 | #endif /* CONFIG_NCPFS_PACKET_SIGNING */ |
@@ -720,6 +728,9 @@ out_nls: | |||
720 | unload_nls(server->nls_io); | 728 | unload_nls(server->nls_io); |
721 | unload_nls(server->nls_vol); | 729 | unload_nls(server->nls_vol); |
722 | #endif | 730 | #endif |
731 | mutex_destroy(&server->rcv.creq_mutex); | ||
732 | mutex_destroy(&server->root_setup_lock); | ||
733 | mutex_destroy(&server->mutex); | ||
723 | out_fput2: | 734 | out_fput2: |
724 | if (server->info_filp) | 735 | if (server->info_filp) |
725 | fput(server->info_filp); | 736 | fput(server->info_filp); |
@@ -743,8 +754,6 @@ static void ncp_put_super(struct super_block *sb) | |||
743 | { | 754 | { |
744 | struct ncp_server *server = NCP_SBP(sb); | 755 | struct ncp_server *server = NCP_SBP(sb); |
745 | 756 | ||
746 | lock_kernel(); | ||
747 | |||
748 | ncp_lock_server(server); | 757 | ncp_lock_server(server); |
749 | ncp_disconnect(server); | 758 | ncp_disconnect(server); |
750 | ncp_unlock_server(server); | 759 | ncp_unlock_server(server); |
@@ -756,6 +765,9 @@ static void ncp_put_super(struct super_block *sb) | |||
756 | unload_nls(server->nls_vol); | 765 | unload_nls(server->nls_vol); |
757 | unload_nls(server->nls_io); | 766 | unload_nls(server->nls_io); |
758 | #endif /* CONFIG_NCPFS_NLS */ | 767 | #endif /* CONFIG_NCPFS_NLS */ |
768 | mutex_destroy(&server->rcv.creq_mutex); | ||
769 | mutex_destroy(&server->root_setup_lock); | ||
770 | mutex_destroy(&server->mutex); | ||
759 | 771 | ||
760 | if (server->info_filp) | 772 | if (server->info_filp) |
761 | fput(server->info_filp); | 773 | fput(server->info_filp); |
@@ -771,8 +783,6 @@ static void ncp_put_super(struct super_block *sb) | |||
771 | vfree(server->packet); | 783 | vfree(server->packet); |
772 | sb->s_fs_info = NULL; | 784 | sb->s_fs_info = NULL; |
773 | kfree(server); | 785 | kfree(server); |
774 | |||
775 | unlock_kernel(); | ||
776 | } | 786 | } |
777 | 787 | ||
778 | static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) | 788 | static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) |
@@ -851,10 +861,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) | |||
851 | 861 | ||
852 | result = -EIO; | 862 | result = -EIO; |
853 | 863 | ||
854 | lock_kernel(); | ||
855 | |||
856 | server = NCP_SERVER(inode); | 864 | server = NCP_SERVER(inode); |
857 | if ((!server) || !ncp_conn_valid(server)) | 865 | if (!server) /* How this could happen? */ |
858 | goto out; | 866 | goto out; |
859 | 867 | ||
860 | /* ageing the dentry to force validation */ | 868 | /* ageing the dentry to force validation */ |
@@ -981,8 +989,6 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) | |||
981 | result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), | 989 | result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), |
982 | inode, info_mask, &info); | 990 | inode, info_mask, &info); |
983 | if (result != 0) { | 991 | if (result != 0) { |
984 | result = -EACCES; | ||
985 | |||
986 | if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { | 992 | if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { |
987 | /* NetWare seems not to allow this. I | 993 | /* NetWare seems not to allow this. I |
988 | do not know why. So, just tell the | 994 | do not know why. So, just tell the |
@@ -1005,7 +1011,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) | |||
1005 | mark_inode_dirty(inode); | 1011 | mark_inode_dirty(inode); |
1006 | 1012 | ||
1007 | out: | 1013 | out: |
1008 | unlock_kernel(); | 1014 | if (result > 0) |
1015 | result = -EACCES; | ||
1009 | return result; | 1016 | return result; |
1010 | } | 1017 | } |
1011 | 1018 | ||
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 84a8cfc4e38e..c2a1f9a155c3 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c | |||
@@ -35,16 +35,11 @@ | |||
35 | #define NCP_PACKET_SIZE_INTERNAL 65536 | 35 | #define NCP_PACKET_SIZE_INTERNAL 65536 |
36 | 36 | ||
37 | static int | 37 | static int |
38 | ncp_get_fs_info(struct ncp_server * server, struct file *file, | 38 | ncp_get_fs_info(struct ncp_server * server, struct inode *inode, |
39 | struct ncp_fs_info __user *arg) | 39 | struct ncp_fs_info __user *arg) |
40 | { | 40 | { |
41 | struct inode *inode = file->f_path.dentry->d_inode; | ||
42 | struct ncp_fs_info info; | 41 | struct ncp_fs_info info; |
43 | 42 | ||
44 | if (file_permission(file, MAY_WRITE) != 0 | ||
45 | && current_uid() != server->m.mounted_uid) | ||
46 | return -EACCES; | ||
47 | |||
48 | if (copy_from_user(&info, arg, sizeof(info))) | 43 | if (copy_from_user(&info, arg, sizeof(info))) |
49 | return -EFAULT; | 44 | return -EFAULT; |
50 | 45 | ||
@@ -65,16 +60,11 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file, | |||
65 | } | 60 | } |
66 | 61 | ||
67 | static int | 62 | static int |
68 | ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, | 63 | ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode, |
69 | struct ncp_fs_info_v2 __user * arg) | 64 | struct ncp_fs_info_v2 __user * arg) |
70 | { | 65 | { |
71 | struct inode *inode = file->f_path.dentry->d_inode; | ||
72 | struct ncp_fs_info_v2 info2; | 66 | struct ncp_fs_info_v2 info2; |
73 | 67 | ||
74 | if (file_permission(file, MAY_WRITE) != 0 | ||
75 | && current_uid() != server->m.mounted_uid) | ||
76 | return -EACCES; | ||
77 | |||
78 | if (copy_from_user(&info2, arg, sizeof(info2))) | 68 | if (copy_from_user(&info2, arg, sizeof(info2))) |
79 | return -EFAULT; | 69 | return -EFAULT; |
80 | 70 | ||
@@ -136,16 +126,11 @@ struct compat_ncp_privatedata_ioctl | |||
136 | #define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) | 126 | #define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) |
137 | 127 | ||
138 | static int | 128 | static int |
139 | ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file, | 129 | ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode, |
140 | struct compat_ncp_fs_info_v2 __user * arg) | 130 | struct compat_ncp_fs_info_v2 __user * arg) |
141 | { | 131 | { |
142 | struct inode *inode = file->f_path.dentry->d_inode; | ||
143 | struct compat_ncp_fs_info_v2 info2; | 132 | struct compat_ncp_fs_info_v2 info2; |
144 | 133 | ||
145 | if (file_permission(file, MAY_WRITE) != 0 | ||
146 | && current_uid() != server->m.mounted_uid) | ||
147 | return -EACCES; | ||
148 | |||
149 | if (copy_from_user(&info2, arg, sizeof(info2))) | 134 | if (copy_from_user(&info2, arg, sizeof(info2))) |
150 | return -EFAULT; | 135 | return -EFAULT; |
151 | 136 | ||
@@ -182,11 +167,8 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) | |||
182 | struct nls_table *iocharset; | 167 | struct nls_table *iocharset; |
183 | struct nls_table *oldset_io; | 168 | struct nls_table *oldset_io; |
184 | struct nls_table *oldset_cp; | 169 | struct nls_table *oldset_cp; |
185 | 170 | int utf8; | |
186 | if (!capable(CAP_SYS_ADMIN)) | 171 | int err; |
187 | return -EACCES; | ||
188 | if (server->root_setuped) | ||
189 | return -EBUSY; | ||
190 | 172 | ||
191 | if (copy_from_user(&user, arg, sizeof(user))) | 173 | if (copy_from_user(&user, arg, sizeof(user))) |
192 | return -EFAULT; | 174 | return -EFAULT; |
@@ -206,28 +188,40 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) | |||
206 | user.iocharset[NCP_IOCSNAME_LEN] = 0; | 188 | user.iocharset[NCP_IOCSNAME_LEN] = 0; |
207 | if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { | 189 | if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { |
208 | iocharset = load_nls_default(); | 190 | iocharset = load_nls_default(); |
209 | NCP_CLR_FLAG(server, NCP_FLAG_UTF8); | 191 | utf8 = 0; |
210 | } else if (!strcmp(user.iocharset, "utf8")) { | 192 | } else if (!strcmp(user.iocharset, "utf8")) { |
211 | iocharset = load_nls_default(); | 193 | iocharset = load_nls_default(); |
212 | NCP_SET_FLAG(server, NCP_FLAG_UTF8); | 194 | utf8 = 1; |
213 | } else { | 195 | } else { |
214 | iocharset = load_nls(user.iocharset); | 196 | iocharset = load_nls(user.iocharset); |
215 | if (!iocharset) { | 197 | if (!iocharset) { |
216 | unload_nls(codepage); | 198 | unload_nls(codepage); |
217 | return -EBADRQC; | 199 | return -EBADRQC; |
218 | } | 200 | } |
219 | NCP_CLR_FLAG(server, NCP_FLAG_UTF8); | 201 | utf8 = 0; |
220 | } | 202 | } |
221 | 203 | ||
222 | oldset_cp = server->nls_vol; | 204 | mutex_lock(&server->root_setup_lock); |
223 | server->nls_vol = codepage; | 205 | if (server->root_setuped) { |
224 | oldset_io = server->nls_io; | 206 | oldset_cp = codepage; |
225 | server->nls_io = iocharset; | 207 | oldset_io = iocharset; |
226 | 208 | err = -EBUSY; | |
209 | } else { | ||
210 | if (utf8) | ||
211 | NCP_SET_FLAG(server, NCP_FLAG_UTF8); | ||
212 | else | ||
213 | NCP_CLR_FLAG(server, NCP_FLAG_UTF8); | ||
214 | oldset_cp = server->nls_vol; | ||
215 | server->nls_vol = codepage; | ||
216 | oldset_io = server->nls_io; | ||
217 | server->nls_io = iocharset; | ||
218 | err = 0; | ||
219 | } | ||
220 | mutex_unlock(&server->root_setup_lock); | ||
227 | unload_nls(oldset_cp); | 221 | unload_nls(oldset_cp); |
228 | unload_nls(oldset_io); | 222 | unload_nls(oldset_io); |
229 | 223 | ||
230 | return 0; | 224 | return err; |
231 | } | 225 | } |
232 | 226 | ||
233 | static int | 227 | static int |
@@ -237,6 +231,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) | |||
237 | int len; | 231 | int len; |
238 | 232 | ||
239 | memset(&user, 0, sizeof(user)); | 233 | memset(&user, 0, sizeof(user)); |
234 | mutex_lock(&server->root_setup_lock); | ||
240 | if (server->nls_vol && server->nls_vol->charset) { | 235 | if (server->nls_vol && server->nls_vol->charset) { |
241 | len = strlen(server->nls_vol->charset); | 236 | len = strlen(server->nls_vol->charset); |
242 | if (len > NCP_IOCSNAME_LEN) | 237 | if (len > NCP_IOCSNAME_LEN) |
@@ -254,6 +249,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) | |||
254 | strncpy(user.iocharset, server->nls_io->charset, len); | 249 | strncpy(user.iocharset, server->nls_io->charset, len); |
255 | user.iocharset[len] = 0; | 250 | user.iocharset[len] = 0; |
256 | } | 251 | } |
252 | mutex_unlock(&server->root_setup_lock); | ||
257 | 253 | ||
258 | if (copy_to_user(arg, &user, sizeof(user))) | 254 | if (copy_to_user(arg, &user, sizeof(user))) |
259 | return -EFAULT; | 255 | return -EFAULT; |
@@ -261,25 +257,19 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) | |||
261 | } | 257 | } |
262 | #endif /* CONFIG_NCPFS_NLS */ | 258 | #endif /* CONFIG_NCPFS_NLS */ |
263 | 259 | ||
264 | static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 260 | static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg) |
265 | { | 261 | { |
266 | struct inode *inode = filp->f_dentry->d_inode; | ||
267 | struct ncp_server *server = NCP_SERVER(inode); | 262 | struct ncp_server *server = NCP_SERVER(inode); |
268 | int result; | 263 | int result; |
269 | struct ncp_ioctl_request request; | 264 | struct ncp_ioctl_request request; |
270 | char* bouncebuffer; | 265 | char* bouncebuffer; |
271 | void __user *argp = (void __user *)arg; | 266 | void __user *argp = (void __user *)arg; |
272 | uid_t uid = current_uid(); | ||
273 | 267 | ||
274 | switch (cmd) { | 268 | switch (cmd) { |
275 | #ifdef CONFIG_COMPAT | 269 | #ifdef CONFIG_COMPAT |
276 | case NCP_IOC_NCPREQUEST_32: | 270 | case NCP_IOC_NCPREQUEST_32: |
277 | #endif | 271 | #endif |
278 | case NCP_IOC_NCPREQUEST: | 272 | case NCP_IOC_NCPREQUEST: |
279 | if (file_permission(filp, MAY_WRITE) != 0 | ||
280 | && uid != server->m.mounted_uid) | ||
281 | return -EACCES; | ||
282 | |||
283 | #ifdef CONFIG_COMPAT | 273 | #ifdef CONFIG_COMPAT |
284 | if (cmd == NCP_IOC_NCPREQUEST_32) { | 274 | if (cmd == NCP_IOC_NCPREQUEST_32) { |
285 | struct compat_ncp_ioctl_request request32; | 275 | struct compat_ncp_ioctl_request request32; |
@@ -314,7 +304,7 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
314 | server->current_size = request.size; | 304 | server->current_size = request.size; |
315 | memcpy(server->packet, bouncebuffer, request.size); | 305 | memcpy(server->packet, bouncebuffer, request.size); |
316 | 306 | ||
317 | result = ncp_request2(server, request.function, | 307 | result = ncp_request2(server, request.function, |
318 | bouncebuffer, NCP_PACKET_SIZE_INTERNAL); | 308 | bouncebuffer, NCP_PACKET_SIZE_INTERNAL); |
319 | if (result < 0) | 309 | if (result < 0) |
320 | result = -EIO; | 310 | result = -EIO; |
@@ -331,69 +321,69 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
331 | 321 | ||
332 | case NCP_IOC_CONN_LOGGED_IN: | 322 | case NCP_IOC_CONN_LOGGED_IN: |
333 | 323 | ||
334 | if (!capable(CAP_SYS_ADMIN)) | ||
335 | return -EACCES; | ||
336 | if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) | 324 | if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) |
337 | return -EINVAL; | 325 | return -EINVAL; |
326 | mutex_lock(&server->root_setup_lock); | ||
338 | if (server->root_setuped) | 327 | if (server->root_setuped) |
339 | return -EBUSY; | 328 | result = -EBUSY; |
340 | server->root_setuped = 1; | 329 | else { |
341 | return ncp_conn_logged_in(inode->i_sb); | 330 | result = ncp_conn_logged_in(inode->i_sb); |
331 | if (result == 0) | ||
332 | server->root_setuped = 1; | ||
333 | } | ||
334 | mutex_unlock(&server->root_setup_lock); | ||
335 | return result; | ||
342 | 336 | ||
343 | case NCP_IOC_GET_FS_INFO: | 337 | case NCP_IOC_GET_FS_INFO: |
344 | return ncp_get_fs_info(server, filp, argp); | 338 | return ncp_get_fs_info(server, inode, argp); |
345 | 339 | ||
346 | case NCP_IOC_GET_FS_INFO_V2: | 340 | case NCP_IOC_GET_FS_INFO_V2: |
347 | return ncp_get_fs_info_v2(server, filp, argp); | 341 | return ncp_get_fs_info_v2(server, inode, argp); |
348 | 342 | ||
349 | #ifdef CONFIG_COMPAT | 343 | #ifdef CONFIG_COMPAT |
350 | case NCP_IOC_GET_FS_INFO_V2_32: | 344 | case NCP_IOC_GET_FS_INFO_V2_32: |
351 | return ncp_get_compat_fs_info_v2(server, filp, argp); | 345 | return ncp_get_compat_fs_info_v2(server, inode, argp); |
352 | #endif | 346 | #endif |
353 | /* we have too many combinations of CONFIG_COMPAT, | 347 | /* we have too many combinations of CONFIG_COMPAT, |
354 | * CONFIG_64BIT and CONFIG_UID16, so just handle | 348 | * CONFIG_64BIT and CONFIG_UID16, so just handle |
355 | * any of the possible ioctls */ | 349 | * any of the possible ioctls */ |
356 | case NCP_IOC_GETMOUNTUID16: | 350 | case NCP_IOC_GETMOUNTUID16: |
357 | case NCP_IOC_GETMOUNTUID32: | 351 | { |
358 | case NCP_IOC_GETMOUNTUID64: | ||
359 | if (file_permission(filp, MAY_READ) != 0 | ||
360 | && uid != server->m.mounted_uid) | ||
361 | return -EACCES; | ||
362 | |||
363 | if (cmd == NCP_IOC_GETMOUNTUID16) { | ||
364 | u16 uid; | 352 | u16 uid; |
353 | |||
365 | SET_UID(uid, server->m.mounted_uid); | 354 | SET_UID(uid, server->m.mounted_uid); |
366 | if (put_user(uid, (u16 __user *)argp)) | 355 | if (put_user(uid, (u16 __user *)argp)) |
367 | return -EFAULT; | 356 | return -EFAULT; |
368 | } else if (cmd == NCP_IOC_GETMOUNTUID32) { | 357 | return 0; |
369 | if (put_user(server->m.mounted_uid, | ||
370 | (u32 __user *)argp)) | ||
371 | return -EFAULT; | ||
372 | } else { | ||
373 | if (put_user(server->m.mounted_uid, | ||
374 | (u64 __user *)argp)) | ||
375 | return -EFAULT; | ||
376 | } | 358 | } |
359 | case NCP_IOC_GETMOUNTUID32: | ||
360 | if (put_user(server->m.mounted_uid, | ||
361 | (u32 __user *)argp)) | ||
362 | return -EFAULT; | ||
363 | return 0; | ||
364 | case NCP_IOC_GETMOUNTUID64: | ||
365 | if (put_user(server->m.mounted_uid, | ||
366 | (u64 __user *)argp)) | ||
367 | return -EFAULT; | ||
377 | return 0; | 368 | return 0; |
378 | 369 | ||
379 | case NCP_IOC_GETROOT: | 370 | case NCP_IOC_GETROOT: |
380 | { | 371 | { |
381 | struct ncp_setroot_ioctl sr; | 372 | struct ncp_setroot_ioctl sr; |
382 | 373 | ||
383 | if (file_permission(filp, MAY_READ) != 0 | 374 | result = -EACCES; |
384 | && uid != server->m.mounted_uid) | 375 | mutex_lock(&server->root_setup_lock); |
385 | return -EACCES; | ||
386 | |||
387 | if (server->m.mounted_vol[0]) { | 376 | if (server->m.mounted_vol[0]) { |
388 | struct dentry* dentry = inode->i_sb->s_root; | 377 | struct dentry* dentry = inode->i_sb->s_root; |
389 | 378 | ||
390 | if (dentry) { | 379 | if (dentry) { |
391 | struct inode* s_inode = dentry->d_inode; | 380 | struct inode* s_inode = dentry->d_inode; |
392 | 381 | ||
393 | if (s_inode) { | 382 | if (s_inode) { |
394 | sr.volNumber = NCP_FINFO(s_inode)->volNumber; | 383 | sr.volNumber = NCP_FINFO(s_inode)->volNumber; |
395 | sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; | 384 | sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; |
396 | sr.namespace = server->name_space[sr.volNumber]; | 385 | sr.namespace = server->name_space[sr.volNumber]; |
386 | result = 0; | ||
397 | } else | 387 | } else |
398 | DPRINTK("ncpfs: s_root->d_inode==NULL\n"); | 388 | DPRINTK("ncpfs: s_root->d_inode==NULL\n"); |
399 | } else | 389 | } else |
@@ -402,10 +392,12 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
402 | sr.volNumber = -1; | 392 | sr.volNumber = -1; |
403 | sr.namespace = 0; | 393 | sr.namespace = 0; |
404 | sr.dirEntNum = 0; | 394 | sr.dirEntNum = 0; |
395 | result = 0; | ||
405 | } | 396 | } |
406 | if (copy_to_user(argp, &sr, sizeof(sr))) | 397 | mutex_unlock(&server->root_setup_lock); |
407 | return -EFAULT; | 398 | if (!result && copy_to_user(argp, &sr, sizeof(sr))) |
408 | return 0; | 399 | result = -EFAULT; |
400 | return result; | ||
409 | } | 401 | } |
410 | 402 | ||
411 | case NCP_IOC_SETROOT: | 403 | case NCP_IOC_SETROOT: |
@@ -416,103 +408,114 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
416 | __le32 dosde; | 408 | __le32 dosde; |
417 | struct dentry* dentry; | 409 | struct dentry* dentry; |
418 | 410 | ||
419 | if (!capable(CAP_SYS_ADMIN)) | ||
420 | { | ||
421 | return -EACCES; | ||
422 | } | ||
423 | if (server->root_setuped) return -EBUSY; | ||
424 | if (copy_from_user(&sr, argp, sizeof(sr))) | 411 | if (copy_from_user(&sr, argp, sizeof(sr))) |
425 | return -EFAULT; | 412 | return -EFAULT; |
426 | if (sr.volNumber < 0) { | 413 | mutex_lock(&server->root_setup_lock); |
427 | server->m.mounted_vol[0] = 0; | 414 | if (server->root_setuped) |
428 | vnum = NCP_NUMBER_OF_VOLUMES; | 415 | result = -EBUSY; |
429 | de = 0; | 416 | else { |
430 | dosde = 0; | 417 | if (sr.volNumber < 0) { |
431 | } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { | 418 | server->m.mounted_vol[0] = 0; |
432 | return -EINVAL; | 419 | vnum = NCP_NUMBER_OF_VOLUMES; |
433 | } else if (ncp_mount_subdir(server, sr.volNumber, | 420 | de = 0; |
434 | sr.namespace, sr.dirEntNum, | 421 | dosde = 0; |
435 | &vnum, &de, &dosde)) { | 422 | result = 0; |
436 | return -ENOENT; | 423 | } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { |
437 | } | 424 | result = -EINVAL; |
438 | 425 | } else if (ncp_mount_subdir(server, sr.volNumber, | |
439 | dentry = inode->i_sb->s_root; | 426 | sr.namespace, sr.dirEntNum, |
440 | server->root_setuped = 1; | 427 | &vnum, &de, &dosde)) { |
441 | if (dentry) { | 428 | result = -ENOENT; |
442 | struct inode* s_inode = dentry->d_inode; | ||
443 | |||
444 | if (s_inode) { | ||
445 | NCP_FINFO(s_inode)->volNumber = vnum; | ||
446 | NCP_FINFO(s_inode)->dirEntNum = de; | ||
447 | NCP_FINFO(s_inode)->DosDirNum = dosde; | ||
448 | } else | 429 | } else |
449 | DPRINTK("ncpfs: s_root->d_inode==NULL\n"); | 430 | result = 0; |
450 | } else | 431 | |
451 | DPRINTK("ncpfs: s_root==NULL\n"); | 432 | if (result == 0) { |
433 | dentry = inode->i_sb->s_root; | ||
434 | if (dentry) { | ||
435 | struct inode* s_inode = dentry->d_inode; | ||
436 | |||
437 | if (s_inode) { | ||
438 | NCP_FINFO(s_inode)->volNumber = vnum; | ||
439 | NCP_FINFO(s_inode)->dirEntNum = de; | ||
440 | NCP_FINFO(s_inode)->DosDirNum = dosde; | ||
441 | server->root_setuped = 1; | ||
442 | } else { | ||
443 | DPRINTK("ncpfs: s_root->d_inode==NULL\n"); | ||
444 | result = -EIO; | ||
445 | } | ||
446 | } else { | ||
447 | DPRINTK("ncpfs: s_root==NULL\n"); | ||
448 | result = -EIO; | ||
449 | } | ||
450 | } | ||
451 | result = 0; | ||
452 | } | ||
453 | mutex_unlock(&server->root_setup_lock); | ||
452 | 454 | ||
453 | return 0; | 455 | return result; |
454 | } | 456 | } |
455 | 457 | ||
456 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 458 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
457 | case NCP_IOC_SIGN_INIT: | 459 | case NCP_IOC_SIGN_INIT: |
458 | if (file_permission(filp, MAY_WRITE) != 0 | 460 | { |
459 | && uid != server->m.mounted_uid) | 461 | struct ncp_sign_init sign; |
460 | return -EACCES; | ||
461 | |||
462 | if (argp) { | ||
463 | if (server->sign_wanted) | ||
464 | { | ||
465 | struct ncp_sign_init sign; | ||
466 | 462 | ||
463 | if (argp) | ||
467 | if (copy_from_user(&sign, argp, sizeof(sign))) | 464 | if (copy_from_user(&sign, argp, sizeof(sign))) |
468 | return -EFAULT; | 465 | return -EFAULT; |
469 | memcpy(server->sign_root,sign.sign_root,8); | 466 | ncp_lock_server(server); |
470 | memcpy(server->sign_last,sign.sign_last,16); | 467 | mutex_lock(&server->rcv.creq_mutex); |
471 | server->sign_active = 1; | 468 | if (argp) { |
469 | if (server->sign_wanted) { | ||
470 | memcpy(server->sign_root,sign.sign_root,8); | ||
471 | memcpy(server->sign_last,sign.sign_last,16); | ||
472 | server->sign_active = 1; | ||
473 | } | ||
474 | /* ignore when signatures not wanted */ | ||
475 | } else { | ||
476 | server->sign_active = 0; | ||
472 | } | 477 | } |
473 | /* ignore when signatures not wanted */ | 478 | mutex_unlock(&server->rcv.creq_mutex); |
474 | } else { | 479 | ncp_unlock_server(server); |
475 | server->sign_active = 0; | 480 | return 0; |
476 | } | 481 | } |
477 | return 0; | 482 | |
478 | |||
479 | case NCP_IOC_SIGN_WANTED: | 483 | case NCP_IOC_SIGN_WANTED: |
480 | if (file_permission(filp, MAY_READ) != 0 | 484 | { |
481 | && uid != server->m.mounted_uid) | 485 | int state; |
482 | return -EACCES; | 486 | |
483 | 487 | ncp_lock_server(server); | |
484 | if (put_user(server->sign_wanted, (int __user *)argp)) | 488 | state = server->sign_wanted; |
485 | return -EFAULT; | 489 | ncp_unlock_server(server); |
486 | return 0; | 490 | if (put_user(state, (int __user *)argp)) |
491 | return -EFAULT; | ||
492 | return 0; | ||
493 | } | ||
487 | 494 | ||
488 | case NCP_IOC_SET_SIGN_WANTED: | 495 | case NCP_IOC_SET_SIGN_WANTED: |
489 | { | 496 | { |
490 | int newstate; | 497 | int newstate; |
491 | 498 | ||
492 | if (file_permission(filp, MAY_WRITE) != 0 | ||
493 | && uid != server->m.mounted_uid) | ||
494 | return -EACCES; | ||
495 | |||
496 | /* get only low 8 bits... */ | 499 | /* get only low 8 bits... */ |
497 | if (get_user(newstate, (unsigned char __user *)argp)) | 500 | if (get_user(newstate, (unsigned char __user *)argp)) |
498 | return -EFAULT; | 501 | return -EFAULT; |
502 | result = 0; | ||
503 | ncp_lock_server(server); | ||
499 | if (server->sign_active) { | 504 | if (server->sign_active) { |
500 | /* cannot turn signatures OFF when active */ | 505 | /* cannot turn signatures OFF when active */ |
501 | if (!newstate) return -EINVAL; | 506 | if (!newstate) |
507 | result = -EINVAL; | ||
502 | } else { | 508 | } else { |
503 | server->sign_wanted = newstate != 0; | 509 | server->sign_wanted = newstate != 0; |
504 | } | 510 | } |
505 | return 0; | 511 | ncp_unlock_server(server); |
512 | return result; | ||
506 | } | 513 | } |
507 | 514 | ||
508 | #endif /* CONFIG_NCPFS_PACKET_SIGNING */ | 515 | #endif /* CONFIG_NCPFS_PACKET_SIGNING */ |
509 | 516 | ||
510 | #ifdef CONFIG_NCPFS_IOCTL_LOCKING | 517 | #ifdef CONFIG_NCPFS_IOCTL_LOCKING |
511 | case NCP_IOC_LOCKUNLOCK: | 518 | case NCP_IOC_LOCKUNLOCK: |
512 | if (file_permission(filp, MAY_WRITE) != 0 | ||
513 | && uid != server->m.mounted_uid) | ||
514 | return -EACCES; | ||
515 | |||
516 | { | 519 | { |
517 | struct ncp_lock_ioctl rqdata; | 520 | struct ncp_lock_ioctl rqdata; |
518 | 521 | ||
@@ -541,16 +544,13 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
541 | { | 544 | { |
542 | return result; | 545 | return result; |
543 | } | 546 | } |
544 | result = -EIO; | ||
545 | if (!ncp_conn_valid(server)) | ||
546 | goto outrel; | ||
547 | result = -EISDIR; | 547 | result = -EISDIR; |
548 | if (!S_ISREG(inode->i_mode)) | 548 | if (!S_ISREG(inode->i_mode)) |
549 | goto outrel; | 549 | goto outrel; |
550 | if (rqdata.cmd == NCP_LOCK_CLEAR) | 550 | if (rqdata.cmd == NCP_LOCK_CLEAR) |
551 | { | 551 | { |
552 | result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), | 552 | result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), |
553 | NCP_FINFO(inode)->file_handle, | 553 | NCP_FINFO(inode)->file_handle, |
554 | rqdata.offset, | 554 | rqdata.offset, |
555 | rqdata.length); | 555 | rqdata.length); |
556 | if (result > 0) result = 0; /* no such lock */ | 556 | if (result > 0) result = 0; /* no such lock */ |
@@ -573,7 +573,7 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
573 | rqdata.timeout); | 573 | rqdata.timeout); |
574 | if (result > 0) result = -EAGAIN; | 574 | if (result > 0) result = -EAGAIN; |
575 | } | 575 | } |
576 | outrel: | 576 | outrel: |
577 | ncp_inode_close(inode); | 577 | ncp_inode_close(inode); |
578 | return result; | 578 | return result; |
579 | } | 579 | } |
@@ -581,60 +581,62 @@ outrel: | |||
581 | 581 | ||
582 | #ifdef CONFIG_COMPAT | 582 | #ifdef CONFIG_COMPAT |
583 | case NCP_IOC_GETOBJECTNAME_32: | 583 | case NCP_IOC_GETOBJECTNAME_32: |
584 | if (uid != server->m.mounted_uid) | ||
585 | return -EACCES; | ||
586 | { | 584 | { |
587 | struct compat_ncp_objectname_ioctl user; | 585 | struct compat_ncp_objectname_ioctl user; |
588 | size_t outl; | 586 | size_t outl; |
589 | 587 | ||
590 | if (copy_from_user(&user, argp, sizeof(user))) | 588 | if (copy_from_user(&user, argp, sizeof(user))) |
591 | return -EFAULT; | 589 | return -EFAULT; |
590 | down_read(&server->auth_rwsem); | ||
592 | user.auth_type = server->auth.auth_type; | 591 | user.auth_type = server->auth.auth_type; |
593 | outl = user.object_name_len; | 592 | outl = user.object_name_len; |
594 | user.object_name_len = server->auth.object_name_len; | 593 | user.object_name_len = server->auth.object_name_len; |
595 | if (outl > user.object_name_len) | 594 | if (outl > user.object_name_len) |
596 | outl = user.object_name_len; | 595 | outl = user.object_name_len; |
596 | result = 0; | ||
597 | if (outl) { | 597 | if (outl) { |
598 | if (copy_to_user(compat_ptr(user.object_name), | 598 | if (copy_to_user(compat_ptr(user.object_name), |
599 | server->auth.object_name, | 599 | server->auth.object_name, |
600 | outl)) return -EFAULT; | 600 | outl)) |
601 | result = -EFAULT; | ||
601 | } | 602 | } |
602 | if (copy_to_user(argp, &user, sizeof(user))) | 603 | up_read(&server->auth_rwsem); |
603 | return -EFAULT; | 604 | if (!result && copy_to_user(argp, &user, sizeof(user))) |
604 | return 0; | 605 | result = -EFAULT; |
606 | return result; | ||
605 | } | 607 | } |
606 | #endif | 608 | #endif |
607 | 609 | ||
608 | case NCP_IOC_GETOBJECTNAME: | 610 | case NCP_IOC_GETOBJECTNAME: |
609 | if (uid != server->m.mounted_uid) | ||
610 | return -EACCES; | ||
611 | { | 611 | { |
612 | struct ncp_objectname_ioctl user; | 612 | struct ncp_objectname_ioctl user; |
613 | size_t outl; | 613 | size_t outl; |
614 | 614 | ||
615 | if (copy_from_user(&user, argp, sizeof(user))) | 615 | if (copy_from_user(&user, argp, sizeof(user))) |
616 | return -EFAULT; | 616 | return -EFAULT; |
617 | down_read(&server->auth_rwsem); | ||
617 | user.auth_type = server->auth.auth_type; | 618 | user.auth_type = server->auth.auth_type; |
618 | outl = user.object_name_len; | 619 | outl = user.object_name_len; |
619 | user.object_name_len = server->auth.object_name_len; | 620 | user.object_name_len = server->auth.object_name_len; |
620 | if (outl > user.object_name_len) | 621 | if (outl > user.object_name_len) |
621 | outl = user.object_name_len; | 622 | outl = user.object_name_len; |
623 | result = 0; | ||
622 | if (outl) { | 624 | if (outl) { |
623 | if (copy_to_user(user.object_name, | 625 | if (copy_to_user(user.object_name, |
624 | server->auth.object_name, | 626 | server->auth.object_name, |
625 | outl)) return -EFAULT; | 627 | outl)) |
628 | result = -EFAULT; | ||
626 | } | 629 | } |
627 | if (copy_to_user(argp, &user, sizeof(user))) | 630 | up_read(&server->auth_rwsem); |
628 | return -EFAULT; | 631 | if (!result && copy_to_user(argp, &user, sizeof(user))) |
629 | return 0; | 632 | result = -EFAULT; |
633 | return result; | ||
630 | } | 634 | } |
631 | 635 | ||
632 | #ifdef CONFIG_COMPAT | 636 | #ifdef CONFIG_COMPAT |
633 | case NCP_IOC_SETOBJECTNAME_32: | 637 | case NCP_IOC_SETOBJECTNAME_32: |
634 | #endif | 638 | #endif |
635 | case NCP_IOC_SETOBJECTNAME: | 639 | case NCP_IOC_SETOBJECTNAME: |
636 | if (uid != server->m.mounted_uid) | ||
637 | return -EACCES; | ||
638 | { | 640 | { |
639 | struct ncp_objectname_ioctl user; | 641 | struct ncp_objectname_ioctl user; |
640 | void* newname; | 642 | void* newname; |
@@ -666,9 +668,7 @@ outrel: | |||
666 | } else { | 668 | } else { |
667 | newname = NULL; | 669 | newname = NULL; |
668 | } | 670 | } |
669 | /* enter critical section */ | 671 | down_write(&server->auth_rwsem); |
670 | /* maybe that kfree can sleep so do that this way */ | ||
671 | /* it is at least more SMP friendly (in future...) */ | ||
672 | oldname = server->auth.object_name; | 672 | oldname = server->auth.object_name; |
673 | oldnamelen = server->auth.object_name_len; | 673 | oldnamelen = server->auth.object_name_len; |
674 | oldprivate = server->priv.data; | 674 | oldprivate = server->priv.data; |
@@ -678,7 +678,7 @@ outrel: | |||
678 | server->auth.object_name = newname; | 678 | server->auth.object_name = newname; |
679 | server->priv.len = 0; | 679 | server->priv.len = 0; |
680 | server->priv.data = NULL; | 680 | server->priv.data = NULL; |
681 | /* leave critical section */ | 681 | up_write(&server->auth_rwsem); |
682 | kfree(oldprivate); | 682 | kfree(oldprivate); |
683 | kfree(oldname); | 683 | kfree(oldname); |
684 | return 0; | 684 | return 0; |
@@ -688,8 +688,6 @@ outrel: | |||
688 | case NCP_IOC_GETPRIVATEDATA_32: | 688 | case NCP_IOC_GETPRIVATEDATA_32: |
689 | #endif | 689 | #endif |
690 | case NCP_IOC_GETPRIVATEDATA: | 690 | case NCP_IOC_GETPRIVATEDATA: |
691 | if (uid != server->m.mounted_uid) | ||
692 | return -EACCES; | ||
693 | { | 691 | { |
694 | struct ncp_privatedata_ioctl user; | 692 | struct ncp_privatedata_ioctl user; |
695 | size_t outl; | 693 | size_t outl; |
@@ -706,14 +704,20 @@ outrel: | |||
706 | if (copy_from_user(&user, argp, sizeof(user))) | 704 | if (copy_from_user(&user, argp, sizeof(user))) |
707 | return -EFAULT; | 705 | return -EFAULT; |
708 | 706 | ||
707 | down_read(&server->auth_rwsem); | ||
709 | outl = user.len; | 708 | outl = user.len; |
710 | user.len = server->priv.len; | 709 | user.len = server->priv.len; |
711 | if (outl > user.len) outl = user.len; | 710 | if (outl > user.len) outl = user.len; |
711 | result = 0; | ||
712 | if (outl) { | 712 | if (outl) { |
713 | if (copy_to_user(user.data, | 713 | if (copy_to_user(user.data, |
714 | server->priv.data, | 714 | server->priv.data, |
715 | outl)) return -EFAULT; | 715 | outl)) |
716 | result = -EFAULT; | ||
716 | } | 717 | } |
718 | up_read(&server->auth_rwsem); | ||
719 | if (result) | ||
720 | return result; | ||
717 | #ifdef CONFIG_COMPAT | 721 | #ifdef CONFIG_COMPAT |
718 | if (cmd == NCP_IOC_GETPRIVATEDATA_32) { | 722 | if (cmd == NCP_IOC_GETPRIVATEDATA_32) { |
719 | struct compat_ncp_privatedata_ioctl user32; | 723 | struct compat_ncp_privatedata_ioctl user32; |
@@ -733,8 +737,6 @@ outrel: | |||
733 | case NCP_IOC_SETPRIVATEDATA_32: | 737 | case NCP_IOC_SETPRIVATEDATA_32: |
734 | #endif | 738 | #endif |
735 | case NCP_IOC_SETPRIVATEDATA: | 739 | case NCP_IOC_SETPRIVATEDATA: |
736 | if (uid != server->m.mounted_uid) | ||
737 | return -EACCES; | ||
738 | { | 740 | { |
739 | struct ncp_privatedata_ioctl user; | 741 | struct ncp_privatedata_ioctl user; |
740 | void* new; | 742 | void* new; |
@@ -762,12 +764,12 @@ outrel: | |||
762 | } else { | 764 | } else { |
763 | new = NULL; | 765 | new = NULL; |
764 | } | 766 | } |
765 | /* enter critical section */ | 767 | down_write(&server->auth_rwsem); |
766 | old = server->priv.data; | 768 | old = server->priv.data; |
767 | oldlen = server->priv.len; | 769 | oldlen = server->priv.len; |
768 | server->priv.len = user.len; | 770 | server->priv.len = user.len; |
769 | server->priv.data = new; | 771 | server->priv.data = new; |
770 | /* leave critical section */ | 772 | up_write(&server->auth_rwsem); |
771 | kfree(old); | 773 | kfree(old); |
772 | return 0; | 774 | return 0; |
773 | } | 775 | } |
@@ -775,17 +777,13 @@ outrel: | |||
775 | #ifdef CONFIG_NCPFS_NLS | 777 | #ifdef CONFIG_NCPFS_NLS |
776 | case NCP_IOC_SETCHARSETS: | 778 | case NCP_IOC_SETCHARSETS: |
777 | return ncp_set_charsets(server, argp); | 779 | return ncp_set_charsets(server, argp); |
778 | 780 | ||
779 | case NCP_IOC_GETCHARSETS: | 781 | case NCP_IOC_GETCHARSETS: |
780 | return ncp_get_charsets(server, argp); | 782 | return ncp_get_charsets(server, argp); |
781 | 783 | ||
782 | #endif /* CONFIG_NCPFS_NLS */ | 784 | #endif /* CONFIG_NCPFS_NLS */ |
783 | 785 | ||
784 | case NCP_IOC_SETDENTRYTTL: | 786 | case NCP_IOC_SETDENTRYTTL: |
785 | if (file_permission(filp, MAY_WRITE) != 0 && | ||
786 | uid != server->m.mounted_uid) | ||
787 | return -EACCES; | ||
788 | |||
789 | { | 787 | { |
790 | u_int32_t user; | 788 | u_int32_t user; |
791 | 789 | ||
@@ -795,13 +793,13 @@ outrel: | |||
795 | if (user > 20000) | 793 | if (user > 20000) |
796 | return -EINVAL; | 794 | return -EINVAL; |
797 | user = (user * HZ) / 1000; | 795 | user = (user * HZ) / 1000; |
798 | server->dentry_ttl = user; | 796 | atomic_set(&server->dentry_ttl, user); |
799 | return 0; | 797 | return 0; |
800 | } | 798 | } |
801 | 799 | ||
802 | case NCP_IOC_GETDENTRYTTL: | 800 | case NCP_IOC_GETDENTRYTTL: |
803 | { | 801 | { |
804 | u_int32_t user = (server->dentry_ttl * 1000) / HZ; | 802 | u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ; |
805 | if (copy_to_user(argp, &user, sizeof(user))) | 803 | if (copy_to_user(argp, &user, sizeof(user))) |
806 | return -EFAULT; | 804 | return -EFAULT; |
807 | return 0; | 805 | return 0; |
@@ -811,59 +809,103 @@ outrel: | |||
811 | return -EINVAL; | 809 | return -EINVAL; |
812 | } | 810 | } |
813 | 811 | ||
814 | static int ncp_ioctl_need_write(unsigned int cmd) | 812 | long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
815 | { | 813 | { |
814 | struct inode *inode = filp->f_dentry->d_inode; | ||
815 | struct ncp_server *server = NCP_SERVER(inode); | ||
816 | uid_t uid = current_uid(); | ||
817 | int need_drop_write = 0; | ||
818 | long ret; | ||
819 | |||
816 | switch (cmd) { | 820 | switch (cmd) { |
817 | case NCP_IOC_GET_FS_INFO: | ||
818 | case NCP_IOC_GET_FS_INFO_V2: | ||
819 | case NCP_IOC_NCPREQUEST: | ||
820 | case NCP_IOC_SETDENTRYTTL: | ||
821 | case NCP_IOC_SIGN_INIT: | ||
822 | case NCP_IOC_LOCKUNLOCK: | ||
823 | case NCP_IOC_SET_SIGN_WANTED: | ||
824 | return 1; | ||
825 | case NCP_IOC_GETOBJECTNAME: | ||
826 | case NCP_IOC_SETOBJECTNAME: | ||
827 | case NCP_IOC_GETPRIVATEDATA: | ||
828 | case NCP_IOC_SETPRIVATEDATA: | ||
829 | case NCP_IOC_SETCHARSETS: | 821 | case NCP_IOC_SETCHARSETS: |
830 | case NCP_IOC_GETCHARSETS: | ||
831 | case NCP_IOC_CONN_LOGGED_IN: | 822 | case NCP_IOC_CONN_LOGGED_IN: |
832 | case NCP_IOC_GETDENTRYTTL: | ||
833 | case NCP_IOC_GETMOUNTUID2: | ||
834 | case NCP_IOC_SIGN_WANTED: | ||
835 | case NCP_IOC_GETROOT: | ||
836 | case NCP_IOC_SETROOT: | 823 | case NCP_IOC_SETROOT: |
837 | return 0; | 824 | if (!capable(CAP_SYS_ADMIN)) { |
838 | default: | 825 | ret = -EACCES; |
839 | /* unknown IOCTL command, assume write */ | 826 | goto out; |
840 | return 1; | 827 | } |
828 | break; | ||
841 | } | 829 | } |
842 | } | 830 | if (server->m.mounted_uid != uid) { |
843 | 831 | switch (cmd) { | |
844 | long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
845 | { | ||
846 | long ret; | ||
847 | |||
848 | lock_kernel(); | ||
849 | if (ncp_ioctl_need_write(cmd)) { | ||
850 | /* | 832 | /* |
851 | * inside the ioctl(), any failures which | 833 | * Only mount owner can issue these ioctls. Information |
852 | * are because of file_permission() are | 834 | * necessary to authenticate to other NDS servers are |
853 | * -EACCESS, so it seems consistent to keep | 835 | * stored here. |
854 | * that here. | ||
855 | */ | 836 | */ |
856 | if (mnt_want_write(filp->f_path.mnt)) { | 837 | case NCP_IOC_GETOBJECTNAME: |
838 | case NCP_IOC_SETOBJECTNAME: | ||
839 | case NCP_IOC_GETPRIVATEDATA: | ||
840 | case NCP_IOC_SETPRIVATEDATA: | ||
841 | #ifdef CONFIG_COMPAT | ||
842 | case NCP_IOC_GETOBJECTNAME_32: | ||
843 | case NCP_IOC_SETOBJECTNAME_32: | ||
844 | case NCP_IOC_GETPRIVATEDATA_32: | ||
845 | case NCP_IOC_SETPRIVATEDATA_32: | ||
846 | #endif | ||
857 | ret = -EACCES; | 847 | ret = -EACCES; |
858 | goto out; | 848 | goto out; |
849 | /* | ||
850 | * These require write access on the inode if user id | ||
851 | * does not match. Note that they do not write to the | ||
852 | * file... But old code did mnt_want_write, so I keep | ||
853 | * it as is. Of course not for mountpoint owner, as | ||
854 | * that breaks read-only mounts altogether as ncpmount | ||
855 | * needs working NCP_IOC_NCPREQUEST and | ||
856 | * NCP_IOC_GET_FS_INFO. Some of these codes (setdentryttl, | ||
857 | * signinit, setsignwanted) should be probably restricted | ||
858 | * to owner only, or even more to CAP_SYS_ADMIN). | ||
859 | */ | ||
860 | case NCP_IOC_GET_FS_INFO: | ||
861 | case NCP_IOC_GET_FS_INFO_V2: | ||
862 | case NCP_IOC_NCPREQUEST: | ||
863 | case NCP_IOC_SETDENTRYTTL: | ||
864 | case NCP_IOC_SIGN_INIT: | ||
865 | case NCP_IOC_LOCKUNLOCK: | ||
866 | case NCP_IOC_SET_SIGN_WANTED: | ||
867 | #ifdef CONFIG_COMPAT | ||
868 | case NCP_IOC_GET_FS_INFO_V2_32: | ||
869 | case NCP_IOC_NCPREQUEST_32: | ||
870 | #endif | ||
871 | ret = mnt_want_write_file(filp); | ||
872 | if (ret) | ||
873 | goto out; | ||
874 | need_drop_write = 1; | ||
875 | ret = inode_permission(inode, MAY_WRITE); | ||
876 | if (ret) | ||
877 | goto outDropWrite; | ||
878 | break; | ||
879 | /* | ||
880 | * Read access required. | ||
881 | */ | ||
882 | case NCP_IOC_GETMOUNTUID16: | ||
883 | case NCP_IOC_GETMOUNTUID32: | ||
884 | case NCP_IOC_GETMOUNTUID64: | ||
885 | case NCP_IOC_GETROOT: | ||
886 | case NCP_IOC_SIGN_WANTED: | ||
887 | ret = inode_permission(inode, MAY_READ); | ||
888 | if (ret) | ||
889 | goto out; | ||
890 | break; | ||
891 | /* | ||
892 | * Anybody can read these. | ||
893 | */ | ||
894 | case NCP_IOC_GETCHARSETS: | ||
895 | case NCP_IOC_GETDENTRYTTL: | ||
896 | default: | ||
897 | /* Three codes below are protected by CAP_SYS_ADMIN above. */ | ||
898 | case NCP_IOC_SETCHARSETS: | ||
899 | case NCP_IOC_CONN_LOGGED_IN: | ||
900 | case NCP_IOC_SETROOT: | ||
901 | break; | ||
859 | } | 902 | } |
860 | } | 903 | } |
861 | ret = __ncp_ioctl(filp, cmd, arg); | 904 | ret = __ncp_ioctl(inode, cmd, arg); |
862 | if (ncp_ioctl_need_write(cmd)) | 905 | outDropWrite: |
906 | if (need_drop_write) | ||
863 | mnt_drop_write(filp->f_path.mnt); | 907 | mnt_drop_write(filp->f_path.mnt); |
864 | |||
865 | out: | 908 | out: |
866 | unlock_kernel(); | ||
867 | return ret; | 909 | return ret; |
868 | } | 910 | } |
869 | 911 | ||
@@ -872,10 +914,8 @@ long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
872 | { | 914 | { |
873 | long ret; | 915 | long ret; |
874 | 916 | ||
875 | lock_kernel(); | ||
876 | arg = (unsigned long) compat_ptr(arg); | 917 | arg = (unsigned long) compat_ptr(arg); |
877 | ret = ncp_ioctl(file, cmd, arg); | 918 | ret = ncp_ioctl(file, cmd, arg); |
878 | unlock_kernel(); | ||
879 | return ret; | 919 | return ret; |
880 | } | 920 | } |
881 | #endif | 921 | #endif |
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c index 0ec6237a5970..a95615a0b6ac 100644 --- a/fs/ncpfs/ncplib_kernel.c +++ b/fs/ncpfs/ncplib_kernel.c | |||
@@ -107,17 +107,17 @@ ncp_reply_data(struct ncp_server *server, int offset) | |||
107 | return &(server->packet[sizeof(struct ncp_reply_header) + offset]); | 107 | return &(server->packet[sizeof(struct ncp_reply_header) + offset]); |
108 | } | 108 | } |
109 | 109 | ||
110 | static inline u8 BVAL(void *data) | 110 | static inline u8 BVAL(const void *data) |
111 | { | 111 | { |
112 | return *(u8 *)data; | 112 | return *(const u8 *)data; |
113 | } | 113 | } |
114 | 114 | ||
115 | static u8 ncp_reply_byte(struct ncp_server *server, int offset) | 115 | static u8 ncp_reply_byte(struct ncp_server *server, int offset) |
116 | { | 116 | { |
117 | return *(u8 *)ncp_reply_data(server, offset); | 117 | return *(const u8 *)ncp_reply_data(server, offset); |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline u16 WVAL_LH(void *data) | 120 | static inline u16 WVAL_LH(const void *data) |
121 | { | 121 | { |
122 | return get_unaligned_le16(data); | 122 | return get_unaligned_le16(data); |
123 | } | 123 | } |
@@ -134,7 +134,7 @@ ncp_reply_be16(struct ncp_server *server, int offset) | |||
134 | return get_unaligned_be16(ncp_reply_data(server, offset)); | 134 | return get_unaligned_be16(ncp_reply_data(server, offset)); |
135 | } | 135 | } |
136 | 136 | ||
137 | static inline u32 DVAL_LH(void *data) | 137 | static inline u32 DVAL_LH(const void *data) |
138 | { | 138 | { |
139 | return get_unaligned_le32(data); | 139 | return get_unaligned_le32(data); |
140 | } | 140 | } |
@@ -349,9 +349,9 @@ int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) { | |||
349 | return result; | 349 | return result; |
350 | } | 350 | } |
351 | 351 | ||
352 | void ncp_extract_file_info(void *structure, struct nw_info_struct *target) | 352 | void ncp_extract_file_info(const void *structure, struct nw_info_struct *target) |
353 | { | 353 | { |
354 | __u8 *name_len; | 354 | const __u8 *name_len; |
355 | const int info_struct_size = offsetof(struct nw_info_struct, nameLen); | 355 | const int info_struct_size = offsetof(struct nw_info_struct, nameLen); |
356 | 356 | ||
357 | memcpy(target, structure, info_struct_size); | 357 | memcpy(target, structure, info_struct_size); |
@@ -364,7 +364,7 @@ void ncp_extract_file_info(void *structure, struct nw_info_struct *target) | |||
364 | } | 364 | } |
365 | 365 | ||
366 | #ifdef CONFIG_NCPFS_NFS_NS | 366 | #ifdef CONFIG_NCPFS_NFS_NS |
367 | static inline void ncp_extract_nfs_info(unsigned char *structure, | 367 | static inline void ncp_extract_nfs_info(const unsigned char *structure, |
368 | struct nw_nfs_info *target) | 368 | struct nw_nfs_info *target) |
369 | { | 369 | { |
370 | target->mode = DVAL_LH(structure); | 370 | target->mode = DVAL_LH(structure); |
@@ -417,7 +417,7 @@ int ncp_obtain_nfs_info(struct ncp_server *server, | |||
417 | * Returns information for a (one-component) name relative to | 417 | * Returns information for a (one-component) name relative to |
418 | * the specified directory. | 418 | * the specified directory. |
419 | */ | 419 | */ |
420 | int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path, | 420 | int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path, |
421 | struct nw_info_struct *target) | 421 | struct nw_info_struct *target) |
422 | { | 422 | { |
423 | __u8 volnum = NCP_FINFO(dir)->volNumber; | 423 | __u8 volnum = NCP_FINFO(dir)->volNumber; |
@@ -452,16 +452,16 @@ out: | |||
452 | #ifdef CONFIG_NCPFS_NFS_NS | 452 | #ifdef CONFIG_NCPFS_NFS_NS |
453 | static int | 453 | static int |
454 | ncp_obtain_DOS_dir_base(struct ncp_server *server, | 454 | ncp_obtain_DOS_dir_base(struct ncp_server *server, |
455 | __u8 volnum, __le32 dirent, | 455 | __u8 ns, __u8 volnum, __le32 dirent, |
456 | char *path, /* At most 1 component */ | 456 | const char *path, /* At most 1 component */ |
457 | __le32 *DOS_dir_base) | 457 | __le32 *DOS_dir_base) |
458 | { | 458 | { |
459 | int result; | 459 | int result; |
460 | 460 | ||
461 | ncp_init_request(server); | 461 | ncp_init_request(server); |
462 | ncp_add_byte(server, 6); /* subfunction */ | 462 | ncp_add_byte(server, 6); /* subfunction */ |
463 | ncp_add_byte(server, server->name_space[volnum]); | 463 | ncp_add_byte(server, ns); |
464 | ncp_add_byte(server, server->name_space[volnum]); | 464 | ncp_add_byte(server, ns); |
465 | ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ | 465 | ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ |
466 | ncp_add_dword(server, RIM_DIRECTORY); | 466 | ncp_add_dword(server, RIM_DIRECTORY); |
467 | ncp_add_handle_path(server, volnum, dirent, 1, path); | 467 | ncp_add_handle_path(server, volnum, dirent, 1, path); |
@@ -523,10 +523,27 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume) | |||
523 | #endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */ | 523 | #endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */ |
524 | } | 524 | } |
525 | 525 | ||
526 | int | ||
527 | ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns) | ||
528 | { | ||
529 | int ns = ncp_get_known_namespace(server, volume); | ||
530 | |||
531 | if (ret_ns) | ||
532 | *ret_ns = ns; | ||
533 | |||
534 | DPRINTK("lookup_vol: namespace[%d] = %d\n", | ||
535 | volume, server->name_space[volume]); | ||
536 | |||
537 | if (server->name_space[volume] == ns) | ||
538 | return 0; | ||
539 | server->name_space[volume] = ns; | ||
540 | return 1; | ||
541 | } | ||
542 | |||
526 | static int | 543 | static int |
527 | ncp_ObtainSpecificDirBase(struct ncp_server *server, | 544 | ncp_ObtainSpecificDirBase(struct ncp_server *server, |
528 | __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base, | 545 | __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base, |
529 | char *path, /* At most 1 component */ | 546 | const char *path, /* At most 1 component */ |
530 | __le32 *dirEntNum, __le32 *DosDirNum) | 547 | __le32 *dirEntNum, __le32 *DosDirNum) |
531 | { | 548 | { |
532 | int result; | 549 | int result; |
@@ -560,14 +577,13 @@ ncp_mount_subdir(struct ncp_server *server, | |||
560 | { | 577 | { |
561 | int dstNS; | 578 | int dstNS; |
562 | int result; | 579 | int result; |
563 | 580 | ||
564 | dstNS = ncp_get_known_namespace(server, volNumber); | 581 | ncp_update_known_namespace(server, volNumber, &dstNS); |
565 | if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, | 582 | if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, |
566 | dirEntNum, NULL, newDirEnt, newDosEnt)) != 0) | 583 | dirEntNum, NULL, newDirEnt, newDosEnt)) != 0) |
567 | { | 584 | { |
568 | return result; | 585 | return result; |
569 | } | 586 | } |
570 | server->name_space[volNumber] = dstNS; | ||
571 | *volume = volNumber; | 587 | *volume = volNumber; |
572 | server->m.mounted_vol[1] = 0; | 588 | server->m.mounted_vol[1] = 0; |
573 | server->m.mounted_vol[0] = 'X'; | 589 | server->m.mounted_vol[0] = 'X'; |
@@ -575,11 +591,10 @@ ncp_mount_subdir(struct ncp_server *server, | |||
575 | } | 591 | } |
576 | 592 | ||
577 | int | 593 | int |
578 | ncp_get_volume_root(struct ncp_server *server, const char *volname, | 594 | ncp_get_volume_root(struct ncp_server *server, |
579 | __u32* volume, __le32* dirent, __le32* dosdirent) | 595 | const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent) |
580 | { | 596 | { |
581 | int result; | 597 | int result; |
582 | __u8 volnum; | ||
583 | 598 | ||
584 | DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname); | 599 | DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname); |
585 | 600 | ||
@@ -601,21 +616,14 @@ ncp_get_volume_root(struct ncp_server *server, const char *volname, | |||
601 | return result; | 616 | return result; |
602 | } | 617 | } |
603 | *dirent = *dosdirent = ncp_reply_dword(server, 4); | 618 | *dirent = *dosdirent = ncp_reply_dword(server, 4); |
604 | volnum = ncp_reply_byte(server, 8); | 619 | *volume = ncp_reply_byte(server, 8); |
605 | ncp_unlock_server(server); | 620 | ncp_unlock_server(server); |
606 | *volume = volnum; | ||
607 | |||
608 | server->name_space[volnum] = ncp_get_known_namespace(server, volnum); | ||
609 | |||
610 | DPRINTK("lookup_vol: namespace[%d] = %d\n", | ||
611 | volnum, server->name_space[volnum]); | ||
612 | |||
613 | return 0; | 621 | return 0; |
614 | } | 622 | } |
615 | 623 | ||
616 | int | 624 | int |
617 | ncp_lookup_volume(struct ncp_server *server, const char *volname, | 625 | ncp_lookup_volume(struct ncp_server *server, |
618 | struct nw_info_struct *target) | 626 | const char *volname, struct nw_info_struct *target) |
619 | { | 627 | { |
620 | int result; | 628 | int result; |
621 | 629 | ||
@@ -625,6 +633,7 @@ ncp_lookup_volume(struct ncp_server *server, const char *volname, | |||
625 | if (result) { | 633 | if (result) { |
626 | return result; | 634 | return result; |
627 | } | 635 | } |
636 | ncp_update_known_namespace(server, target->volNumber, NULL); | ||
628 | target->nameLen = strlen(volname); | 637 | target->nameLen = strlen(volname); |
629 | memcpy(target->entryName, volname, target->nameLen+1); | 638 | memcpy(target->entryName, volname, target->nameLen+1); |
630 | target->attributes = aDIR; | 639 | target->attributes = aDIR; |
@@ -676,8 +685,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent, | |||
676 | { | 685 | { |
677 | int result = 0; | 686 | int result = 0; |
678 | 687 | ||
688 | ncp_init_request(server); | ||
679 | if (server->name_space[volnum] == NW_NS_NFS) { | 689 | if (server->name_space[volnum] == NW_NS_NFS) { |
680 | ncp_init_request(server); | ||
681 | ncp_add_byte(server, 25); /* subfunction */ | 690 | ncp_add_byte(server, 25); /* subfunction */ |
682 | ncp_add_byte(server, server->name_space[volnum]); | 691 | ncp_add_byte(server, server->name_space[volnum]); |
683 | ncp_add_byte(server, NW_NS_NFS); | 692 | ncp_add_byte(server, NW_NS_NFS); |
@@ -690,8 +699,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent, | |||
690 | ncp_add_dword_lh(server, 1); /* nlinks */ | 699 | ncp_add_dword_lh(server, 1); /* nlinks */ |
691 | ncp_add_dword_lh(server, rdev); | 700 | ncp_add_dword_lh(server, rdev); |
692 | result = ncp_request(server, 87); | 701 | result = ncp_request(server, 87); |
693 | ncp_unlock_server(server); | ||
694 | } | 702 | } |
703 | ncp_unlock_server(server); | ||
695 | return result; | 704 | return result; |
696 | } | 705 | } |
697 | #endif | 706 | #endif |
@@ -700,7 +709,7 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent, | |||
700 | static int | 709 | static int |
701 | ncp_DeleteNSEntry(struct ncp_server *server, | 710 | ncp_DeleteNSEntry(struct ncp_server *server, |
702 | __u8 have_dir_base, __u8 volnum, __le32 dirent, | 711 | __u8 have_dir_base, __u8 volnum, __le32 dirent, |
703 | char* name, __u8 ns, __le16 attr) | 712 | const char* name, __u8 ns, __le16 attr) |
704 | { | 713 | { |
705 | int result; | 714 | int result; |
706 | 715 | ||
@@ -734,23 +743,25 @@ ncp_del_file_or_subdir2(struct ncp_server *server, | |||
734 | 743 | ||
735 | int | 744 | int |
736 | ncp_del_file_or_subdir(struct ncp_server *server, | 745 | ncp_del_file_or_subdir(struct ncp_server *server, |
737 | struct inode *dir, char *name) | 746 | struct inode *dir, const char *name) |
738 | { | 747 | { |
739 | __u8 volnum = NCP_FINFO(dir)->volNumber; | 748 | __u8 volnum = NCP_FINFO(dir)->volNumber; |
740 | __le32 dirent = NCP_FINFO(dir)->dirEntNum; | 749 | __le32 dirent = NCP_FINFO(dir)->dirEntNum; |
750 | int name_space; | ||
741 | 751 | ||
752 | name_space = server->name_space[volnum]; | ||
742 | #ifdef CONFIG_NCPFS_NFS_NS | 753 | #ifdef CONFIG_NCPFS_NFS_NS |
743 | if (server->name_space[volnum]==NW_NS_NFS) | 754 | if (name_space == NW_NS_NFS) |
744 | { | 755 | { |
745 | int result; | 756 | int result; |
746 | 757 | ||
747 | result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent); | 758 | result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent); |
748 | if (result) return result; | 759 | if (result) return result; |
749 | return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006)); | 760 | name = NULL; |
761 | name_space = NW_NS_DOS; | ||
750 | } | 762 | } |
751 | else | ||
752 | #endif /* CONFIG_NCPFS_NFS_NS */ | 763 | #endif /* CONFIG_NCPFS_NFS_NS */ |
753 | return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006)); | 764 | return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006)); |
754 | } | 765 | } |
755 | 766 | ||
756 | static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) | 767 | static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) |
@@ -765,7 +776,7 @@ static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) | |||
765 | /* If both dir and name are NULL, then in target there's already a | 776 | /* If both dir and name are NULL, then in target there's already a |
766 | looked-up entry that wants to be opened. */ | 777 | looked-up entry that wants to be opened. */ |
767 | int ncp_open_create_file_or_subdir(struct ncp_server *server, | 778 | int ncp_open_create_file_or_subdir(struct ncp_server *server, |
768 | struct inode *dir, char *name, | 779 | struct inode *dir, const char *name, |
769 | int open_create_mode, | 780 | int open_create_mode, |
770 | __le32 create_attributes, | 781 | __le32 create_attributes, |
771 | __le16 desired_acc_rights, | 782 | __le16 desired_acc_rights, |
@@ -890,8 +901,8 @@ int ncp_search_for_fileset(struct ncp_server *server, | |||
890 | 901 | ||
891 | static int | 902 | static int |
892 | ncp_RenameNSEntry(struct ncp_server *server, | 903 | ncp_RenameNSEntry(struct ncp_server *server, |
893 | struct inode *old_dir, char *old_name, __le16 old_type, | 904 | struct inode *old_dir, const char *old_name, __le16 old_type, |
894 | struct inode *new_dir, char *new_name) | 905 | struct inode *new_dir, const char *new_name) |
895 | { | 906 | { |
896 | int result = -EINVAL; | 907 | int result = -EINVAL; |
897 | 908 | ||
@@ -929,8 +940,8 @@ out: | |||
929 | } | 940 | } |
930 | 941 | ||
931 | int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, | 942 | int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, |
932 | struct inode *old_dir, char *old_name, | 943 | struct inode *old_dir, const char *old_name, |
933 | struct inode *new_dir, char *new_name) | 944 | struct inode *new_dir, const char *new_name) |
934 | { | 945 | { |
935 | int result; | 946 | int result; |
936 | __le16 old_type = cpu_to_le16(0x06); | 947 | __le16 old_type = cpu_to_le16(0x06); |
@@ -958,7 +969,7 @@ int | |||
958 | ncp_read_kernel(struct ncp_server *server, const char *file_id, | 969 | ncp_read_kernel(struct ncp_server *server, const char *file_id, |
959 | __u32 offset, __u16 to_read, char *target, int *bytes_read) | 970 | __u32 offset, __u16 to_read, char *target, int *bytes_read) |
960 | { | 971 | { |
961 | char *source; | 972 | const char *source; |
962 | int result; | 973 | int result; |
963 | 974 | ||
964 | ncp_init_request(server); | 975 | ncp_init_request(server); |
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h index 2441d1ab57dc..3c57eca634ce 100644 --- a/fs/ncpfs/ncplib_kernel.h +++ b/fs/ncpfs/ncplib_kernel.h | |||
@@ -65,10 +65,11 @@ static inline void ncp_inode_close(struct inode *inode) { | |||
65 | atomic_dec(&NCP_FINFO(inode)->opened); | 65 | atomic_dec(&NCP_FINFO(inode)->opened); |
66 | } | 66 | } |
67 | 67 | ||
68 | void ncp_extract_file_info(void* src, struct nw_info_struct* target); | 68 | void ncp_extract_file_info(const void* src, struct nw_info_struct* target); |
69 | int ncp_obtain_info(struct ncp_server *server, struct inode *, char *, | 69 | int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *, |
70 | struct nw_info_struct *target); | 70 | struct nw_info_struct *target); |
71 | int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target); | 71 | int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target); |
72 | int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns); | ||
72 | int ncp_get_volume_root(struct ncp_server *server, const char *volname, | 73 | int ncp_get_volume_root(struct ncp_server *server, const char *volname, |
73 | __u32 *volume, __le32 *dirent, __le32 *dosdirent); | 74 | __u32 *volume, __le32 *dirent, __le32 *dosdirent); |
74 | int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *); | 75 | int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *); |
@@ -80,8 +81,8 @@ int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent, | |||
80 | __u32 mode, __u32 rdev); | 81 | __u32 mode, __u32 rdev); |
81 | 82 | ||
82 | int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); | 83 | int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); |
83 | int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *); | 84 | int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *); |
84 | int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *, | 85 | int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *, |
85 | int, __le32, __le16, struct ncp_entry_info *); | 86 | int, __le32, __le16, struct ncp_entry_info *); |
86 | 87 | ||
87 | int ncp_initialize_search(struct ncp_server *, struct inode *, | 88 | int ncp_initialize_search(struct ncp_server *, struct inode *, |
@@ -93,7 +94,7 @@ int ncp_search_for_fileset(struct ncp_server *server, | |||
93 | char** rbuf, size_t* rsize); | 94 | char** rbuf, size_t* rsize); |
94 | 95 | ||
95 | int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, | 96 | int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, |
96 | struct inode *, char *, struct inode *, char *); | 97 | struct inode *, const char *, struct inode *, const char *); |
97 | 98 | ||
98 | 99 | ||
99 | int | 100 | int |
@@ -170,13 +171,13 @@ static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1, | |||
170 | #endif /* CONFIG_NCPFS_NLS */ | 171 | #endif /* CONFIG_NCPFS_NLS */ |
171 | 172 | ||
172 | #define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) | 173 | #define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) |
173 | #define NCP_MAX_AGE(server) ((server)->dentry_ttl) | 174 | #define NCP_MAX_AGE(server) atomic_read(&(server)->dentry_ttl) |
174 | #define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) | 175 | #define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) |
175 | 176 | ||
176 | static inline void | 177 | static inline void |
177 | ncp_age_dentry(struct ncp_server* server, struct dentry* dentry) | 178 | ncp_age_dentry(struct ncp_server* server, struct dentry* dentry) |
178 | { | 179 | { |
179 | dentry->d_time = jiffies - server->dentry_ttl; | 180 | dentry->d_time = jiffies - NCP_MAX_AGE(server); |
180 | } | 181 | } |
181 | 182 | ||
182 | static inline void | 183 | static inline void |
diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c index 7c0b5c21e6cf..d8b2d7e6910b 100644 --- a/fs/ncpfs/ncpsign_kernel.c +++ b/fs/ncpfs/ncpsign_kernel.c | |||
@@ -15,21 +15,21 @@ | |||
15 | 15 | ||
16 | /* i386: 32-bit, little endian, handles mis-alignment */ | 16 | /* i386: 32-bit, little endian, handles mis-alignment */ |
17 | #ifdef __i386__ | 17 | #ifdef __i386__ |
18 | #define GET_LE32(p) (*(int *)(p)) | 18 | #define GET_LE32(p) (*(const int *)(p)) |
19 | #define PUT_LE32(p,v) { *(int *)(p)=v; } | 19 | #define PUT_LE32(p,v) { *(int *)(p)=v; } |
20 | #else | 20 | #else |
21 | /* from include/ncplib.h */ | 21 | /* from include/ncplib.h */ |
22 | #define BVAL(buf,pos) (((__u8 *)(buf))[pos]) | 22 | #define BVAL(buf,pos) (((const __u8 *)(buf))[pos]) |
23 | #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) | 23 | #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) |
24 | #define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) | 24 | #define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val)) |
25 | 25 | ||
26 | static inline __u16 | 26 | static inline __u16 |
27 | WVAL_LH(__u8 * buf, int pos) | 27 | WVAL_LH(const __u8 * buf, int pos) |
28 | { | 28 | { |
29 | return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; | 29 | return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; |
30 | } | 30 | } |
31 | static inline __u32 | 31 | static inline __u32 |
32 | DVAL_LH(__u8 * buf, int pos) | 32 | DVAL_LH(const __u8 * buf, int pos) |
33 | { | 33 | { |
34 | return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; | 34 | return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; |
35 | } | 35 | } |
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index c7ff6c700a6e..668bd267346e 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c | |||
@@ -746,7 +746,6 @@ static int ncp_do_request(struct ncp_server *server, int size, | |||
746 | return -EIO; | 746 | return -EIO; |
747 | } | 747 | } |
748 | if (!ncp_conn_valid(server)) { | 748 | if (!ncp_conn_valid(server)) { |
749 | printk(KERN_ERR "ncpfs: Connection invalid!\n"); | ||
750 | return -EIO; | 749 | return -EIO; |
751 | } | 750 | } |
752 | { | 751 | { |
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index 4522aed00906..ef663061d5ac 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h | |||
@@ -241,34 +241,6 @@ int ncp_mmap(struct file *, struct vm_area_struct *); | |||
241 | /* linux/fs/ncpfs/ncplib_kernel.c */ | 241 | /* linux/fs/ncpfs/ncplib_kernel.c */ |
242 | int ncp_make_closed(struct inode *); | 242 | int ncp_make_closed(struct inode *); |
243 | 243 | ||
244 | #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) | ||
245 | |||
246 | static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) | ||
247 | { | ||
248 | #ifdef CONFIG_NCPFS_SMALLDOS | ||
249 | int ns = ncp_namespace(i); | ||
250 | |||
251 | if ((ns == NW_NS_DOS) | ||
252 | #ifdef CONFIG_NCPFS_OS2_NS | ||
253 | || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) | ||
254 | #endif /* CONFIG_NCPFS_OS2_NS */ | ||
255 | ) | ||
256 | return 0; | ||
257 | #endif /* CONFIG_NCPFS_SMALLDOS */ | ||
258 | return 1; | ||
259 | } | ||
260 | |||
261 | #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) | ||
262 | |||
263 | static inline int ncp_case_sensitive(struct inode *i) | ||
264 | { | ||
265 | #ifdef CONFIG_NCPFS_NFS_NS | ||
266 | return ncp_namespace(i) == NW_NS_NFS; | ||
267 | #else | ||
268 | return 0; | ||
269 | #endif /* CONFIG_NCPFS_NFS_NS */ | ||
270 | } | ||
271 | |||
272 | #endif /* __KERNEL__ */ | 244 | #endif /* __KERNEL__ */ |
273 | 245 | ||
274 | #endif /* _LINUX_NCP_FS_H */ | 246 | #endif /* _LINUX_NCP_FS_H */ |
diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h index 8da05bc098ca..d64b0e894336 100644 --- a/include/linux/ncp_fs_sb.h +++ b/include/linux/ncp_fs_sb.h | |||
@@ -62,6 +62,7 @@ struct ncp_server { | |||
62 | int ncp_reply_size; | 62 | int ncp_reply_size; |
63 | 63 | ||
64 | int root_setuped; | 64 | int root_setuped; |
65 | struct mutex root_setup_lock; | ||
65 | 66 | ||
66 | /* info for packet signing */ | 67 | /* info for packet signing */ |
67 | int sign_wanted; /* 1=Server needs signed packets */ | 68 | int sign_wanted; /* 1=Server needs signed packets */ |
@@ -81,13 +82,14 @@ struct ncp_server { | |||
81 | size_t len; | 82 | size_t len; |
82 | void* data; | 83 | void* data; |
83 | } priv; | 84 | } priv; |
85 | struct rw_semaphore auth_rwsem; | ||
84 | 86 | ||
85 | /* nls info: codepage for volume and charset for I/O */ | 87 | /* nls info: codepage for volume and charset for I/O */ |
86 | struct nls_table *nls_vol; | 88 | struct nls_table *nls_vol; |
87 | struct nls_table *nls_io; | 89 | struct nls_table *nls_io; |
88 | 90 | ||
89 | /* maximum age in jiffies */ | 91 | /* maximum age in jiffies */ |
90 | int dentry_ttl; | 92 | atomic_t dentry_ttl; |
91 | 93 | ||
92 | /* miscellaneous */ | 94 | /* miscellaneous */ |
93 | unsigned int flags; | 95 | unsigned int flags; |