1/* 2 * fs/cifs_debug.c 3 * 4 * Copyright (C) International Business Machines Corp., 2000,2005 5 * 6 * Modified by Steve French (sfrench@us.ibm.com) 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 16 * the GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22#include <linux/fs.h> 23#include <linux/string.h> 24#include <linux/ctype.h> 25#include <linux/module.h> 26#include <linux/proc_fs.h> 27#include <asm/uaccess.h> 28#include "cifspdu.h" 29#include "cifsglob.h" 30#include "cifsproto.h" 31#include "cifs_debug.h" 32#include "cifsfs.h" 33 34void 35cifs_dump_mem(char *label, void *data, int length) 36{ 37 pr_debug("%s: dump of %d bytes of data at 0x%p\n", label, length, data); 38 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4, 39 data, length, true); 40} 41 42#ifdef CONFIG_CIFS_DEBUG 43void cifs_vfs_err(const char *fmt, ...) 44{ 45 struct va_format vaf; 46 va_list args; 47 48 va_start(args, fmt); 49 50 vaf.fmt = fmt; 51 vaf.va = &args; 52 53 pr_err_ratelimited("CIFS VFS: %pV", &vaf); 54 55 va_end(args); 56} 57#endif 58 59void cifs_dump_detail(void *buf) 60{ 61#ifdef CONFIG_CIFS_DEBUG2 62 struct smb_hdr *smb = (struct smb_hdr *)buf; 63 64 cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n", 65 smb->Command, smb->Status.CifsError, 66 smb->Flags, smb->Flags2, smb->Mid, smb->Pid); 67 cifs_dbg(VFS, "smb buf %p len %u\n", smb, smbCalcSize(smb)); 68#endif /* CONFIG_CIFS_DEBUG2 */ 69} 70 71void cifs_dump_mids(struct TCP_Server_Info *server) 72{ 73#ifdef CONFIG_CIFS_DEBUG2 74 struct list_head *tmp; 75 struct mid_q_entry *mid_entry; 76 77 if (server == NULL) 78 return; 79 80 cifs_dbg(VFS, "Dump pending requests:\n"); 81 spin_lock(&GlobalMid_Lock); 82 list_for_each(tmp, &server->pending_mid_q) { 83 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 84 cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n", 85 mid_entry->mid_state, 86 le16_to_cpu(mid_entry->command), 87 mid_entry->pid, 88 mid_entry->callback_data, 89 mid_entry->mid); 90#ifdef CONFIG_CIFS_STATS2 91 cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n", 92 mid_entry->large_buf, 93 mid_entry->resp_buf, 94 mid_entry->when_received, 95 jiffies); 96#endif /* STATS2 */ 97 cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n", 98 mid_entry->multiRsp, mid_entry->multiEnd); 99 if (mid_entry->resp_buf) { 100 cifs_dump_detail(mid_entry->resp_buf); 101 cifs_dump_mem("existing buf: ", 102 mid_entry->resp_buf, 62); 103 } 104 } 105 spin_unlock(&GlobalMid_Lock); 106#endif /* CONFIG_CIFS_DEBUG2 */ 107} 108 109#ifdef CONFIG_PROC_FS 110static int cifs_debug_data_proc_show(struct seq_file *m, void *v) 111{ 112 struct list_head *tmp1, *tmp2, *tmp3; 113 struct mid_q_entry *mid_entry; 114 struct TCP_Server_Info *server; 115 struct cifs_ses *ses; 116 struct cifs_tcon *tcon; 117 int i, j; 118 __u32 dev_type; 119 120 seq_puts(m, 121 "Display Internal CIFS Data Structures for Debugging\n" 122 "---------------------------------------------------\n"); 123 seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); 124 seq_printf(m, "Features:"); 125#ifdef CONFIG_CIFS_DFS_UPCALL 126 seq_printf(m, " dfs"); 127#endif 128#ifdef CONFIG_CIFS_FSCACHE 129 seq_printf(m, " fscache"); 130#endif 131#ifdef CONFIG_CIFS_WEAK_PW_HASH 132 seq_printf(m, " lanman"); 133#endif 134#ifdef CONFIG_CIFS_POSIX 135 seq_printf(m, " posix"); 136#endif 137#ifdef CONFIG_CIFS_UPCALL 138 seq_printf(m, " spnego"); 139#endif 140#ifdef CONFIG_CIFS_XATTR 141 seq_printf(m, " xattr"); 142#endif 143#ifdef CONFIG_CIFS_ACL 144 seq_printf(m, " acl"); 145#endif 146 seq_putc(m, '\n'); 147 seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); 148 seq_printf(m, "Servers:"); 149 150 i = 0; 151 spin_lock(&cifs_tcp_ses_lock); 152 list_for_each(tmp1, &cifs_tcp_ses_list) { 153 server = list_entry(tmp1, struct TCP_Server_Info, 154 tcp_ses_list); 155 i++; 156 list_for_each(tmp2, &server->smb_ses_list) { 157 ses = list_entry(tmp2, struct cifs_ses, 158 smb_ses_list); 159 if ((ses->serverDomain == NULL) || 160 (ses->serverOS == NULL) || 161 (ses->serverNOS == NULL)) { 162 seq_printf(m, "\n%d) entry for %s not fully " 163 "displayed\n\t", i, ses->serverName); 164 } else { 165 seq_printf(m, 166 "\n%d) Name: %s Domain: %s Uses: %d OS:" 167 " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB" 168 " session status: %d\t", 169 i, ses->serverName, ses->serverDomain, 170 ses->ses_count, ses->serverOS, ses->serverNOS, 171 ses->capabilities, ses->status); 172 } 173 seq_printf(m, "TCP status: %d\n\tLocal Users To " 174 "Server: %d SecMode: 0x%x Req On Wire: %d", 175 server->tcpStatus, server->srv_count, 176 server->sec_mode, in_flight(server)); 177 178#ifdef CONFIG_CIFS_STATS2 179 seq_printf(m, " In Send: %d In MaxReq Wait: %d", 180 atomic_read(&server->in_send), 181 atomic_read(&server->num_waiters)); 182#endif 183 184 seq_puts(m, "\n\tShares:"); 185 j = 0; 186 list_for_each(tmp3, &ses->tcon_list) { 187 tcon = list_entry(tmp3, struct cifs_tcon, 188 tcon_list); 189 ++j; 190 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); 191 seq_printf(m, "\n\t%d) %s Mounts: %d ", j, 192 tcon->treeName, tcon->tc_count); 193 if (tcon->nativeFileSystem) { 194 seq_printf(m, "Type: %s ", 195 tcon->nativeFileSystem); 196 } 197 seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" 198 "\n\tPathComponentMax: %d Status: %d", 199 le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), 200 le32_to_cpu(tcon->fsAttrInfo.Attributes), 201 le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), 202 tcon->tidStatus); 203 if (dev_type == FILE_DEVICE_DISK) 204 seq_puts(m, " type: DISK "); 205 else if (dev_type == FILE_DEVICE_CD_ROM) 206 seq_puts(m, " type: CDROM "); 207 else 208 seq_printf(m, " type: %d ", dev_type); 209 if (server->ops->dump_share_caps) 210 server->ops->dump_share_caps(m, tcon); 211 212 if (tcon->need_reconnect) 213 seq_puts(m, "\tDISCONNECTED "); 214 seq_putc(m, '\n'); 215 } 216 217 seq_puts(m, "\n\tMIDs:\n"); 218 219 spin_lock(&GlobalMid_Lock); 220 list_for_each(tmp3, &server->pending_mid_q) { 221 mid_entry = list_entry(tmp3, struct mid_q_entry, 222 qhead); 223 seq_printf(m, "\tState: %d com: %d pid:" 224 " %d cbdata: %p mid %llu\n", 225 mid_entry->mid_state, 226 le16_to_cpu(mid_entry->command), 227 mid_entry->pid, 228 mid_entry->callback_data, 229 mid_entry->mid); 230 } 231 spin_unlock(&GlobalMid_Lock); 232 } 233 } 234 spin_unlock(&cifs_tcp_ses_lock); 235 seq_putc(m, '\n'); 236 237 /* BB add code to dump additional info such as TCP session info now */ 238 return 0; 239} 240 241static int cifs_debug_data_proc_open(struct inode *inode, struct file *file) 242{ 243 return single_open(file, cifs_debug_data_proc_show, NULL); 244} 245 246static const struct file_operations cifs_debug_data_proc_fops = { 247 .owner = THIS_MODULE, 248 .open = cifs_debug_data_proc_open, 249 .read = seq_read, 250 .llseek = seq_lseek, 251 .release = single_release, 252}; 253 254#ifdef CONFIG_CIFS_STATS 255static ssize_t cifs_stats_proc_write(struct file *file, 256 const char __user *buffer, size_t count, loff_t *ppos) 257{ 258 char c; 259 bool bv; 260 int rc; 261 struct list_head *tmp1, *tmp2, *tmp3; 262 struct TCP_Server_Info *server; 263 struct cifs_ses *ses; 264 struct cifs_tcon *tcon; 265 266 rc = get_user(c, buffer); 267 if (rc) 268 return rc; 269 270 if (strtobool(&c, &bv) == 0) { 271#ifdef CONFIG_CIFS_STATS2 272 atomic_set(&totBufAllocCount, 0); 273 atomic_set(&totSmBufAllocCount, 0); 274#endif /* CONFIG_CIFS_STATS2 */ 275 spin_lock(&cifs_tcp_ses_lock); 276 list_for_each(tmp1, &cifs_tcp_ses_list) { 277 server = list_entry(tmp1, struct TCP_Server_Info, 278 tcp_ses_list); 279 list_for_each(tmp2, &server->smb_ses_list) { 280 ses = list_entry(tmp2, struct cifs_ses, 281 smb_ses_list); 282 list_for_each(tmp3, &ses->tcon_list) { 283 tcon = list_entry(tmp3, 284 struct cifs_tcon, 285 tcon_list); 286 atomic_set(&tcon->num_smbs_sent, 0); 287 if (server->ops->clear_stats) 288 server->ops->clear_stats(tcon); 289 } 290 } 291 } 292 spin_unlock(&cifs_tcp_ses_lock); 293 } 294 295 return count; 296} 297 298static int cifs_stats_proc_show(struct seq_file *m, void *v) 299{ 300 int i; 301 struct list_head *tmp1, *tmp2, *tmp3; 302 struct TCP_Server_Info *server; 303 struct cifs_ses *ses; 304 struct cifs_tcon *tcon; 305 306 seq_printf(m, 307 "Resources in use\nCIFS Session: %d\n", 308 sesInfoAllocCount.counter); 309 seq_printf(m, "Share (unique mount targets): %d\n", 310 tconInfoAllocCount.counter); 311 seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n", 312 bufAllocCount.counter, 313 cifs_min_rcv + tcpSesAllocCount.counter); 314 seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n", 315 smBufAllocCount.counter, cifs_min_small); 316#ifdef CONFIG_CIFS_STATS2 317 seq_printf(m, "Total Large %d Small %d Allocations\n", 318 atomic_read(&totBufAllocCount), 319 atomic_read(&totSmBufAllocCount)); 320#endif /* CONFIG_CIFS_STATS2 */ 321 322 seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount)); 323 seq_printf(m, 324 "\n%d session %d share reconnects\n", 325 tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); 326 327 seq_printf(m, 328 "Total vfs operations: %d maximum at one time: %d\n", 329 GlobalCurrentXid, GlobalMaxActiveXid); 330 331 i = 0; 332 spin_lock(&cifs_tcp_ses_lock); 333 list_for_each(tmp1, &cifs_tcp_ses_list) { 334 server = list_entry(tmp1, struct TCP_Server_Info, 335 tcp_ses_list); 336 list_for_each(tmp2, &server->smb_ses_list) { 337 ses = list_entry(tmp2, struct cifs_ses, 338 smb_ses_list); 339 list_for_each(tmp3, &ses->tcon_list) { 340 tcon = list_entry(tmp3, 341 struct cifs_tcon, 342 tcon_list); 343 i++; 344 seq_printf(m, "\n%d) %s", i, tcon->treeName); 345 if (tcon->need_reconnect) 346 seq_puts(m, "\tDISCONNECTED "); 347 seq_printf(m, "\nSMBs: %d", 348 atomic_read(&tcon->num_smbs_sent)); 349 if (server->ops->print_stats) 350 server->ops->print_stats(m, tcon); 351 } 352 } 353 } 354 spin_unlock(&cifs_tcp_ses_lock); 355 356 seq_putc(m, '\n'); 357 return 0; 358} 359 360static int cifs_stats_proc_open(struct inode *inode, struct file *file) 361{ 362 return single_open(file, cifs_stats_proc_show, NULL); 363} 364 365static const struct file_operations cifs_stats_proc_fops = { 366 .owner = THIS_MODULE, 367 .open = cifs_stats_proc_open, 368 .read = seq_read, 369 .llseek = seq_lseek, 370 .release = single_release, 371 .write = cifs_stats_proc_write, 372}; 373#endif /* STATS */ 374 375static struct proc_dir_entry *proc_fs_cifs; 376static const struct file_operations cifsFYI_proc_fops; 377static const struct file_operations cifs_lookup_cache_proc_fops; 378static const struct file_operations traceSMB_proc_fops; 379static const struct file_operations cifs_security_flags_proc_fops; 380static const struct file_operations cifs_linux_ext_proc_fops; 381 382void 383cifs_proc_init(void) 384{ 385 proc_fs_cifs = proc_mkdir("fs/cifs", NULL); 386 if (proc_fs_cifs == NULL) 387 return; 388 389 proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops); 390 391#ifdef CONFIG_CIFS_STATS 392 proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops); 393#endif /* STATS */ 394 proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); 395 proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); 396 proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, 397 &cifs_linux_ext_proc_fops); 398 proc_create("SecurityFlags", 0, proc_fs_cifs, 399 &cifs_security_flags_proc_fops); 400 proc_create("LookupCacheEnabled", 0, proc_fs_cifs, 401 &cifs_lookup_cache_proc_fops); 402} 403 404void 405cifs_proc_clean(void) 406{ 407 if (proc_fs_cifs == NULL) 408 return; 409 410 remove_proc_entry("DebugData", proc_fs_cifs); 411 remove_proc_entry("cifsFYI", proc_fs_cifs); 412 remove_proc_entry("traceSMB", proc_fs_cifs); 413#ifdef CONFIG_CIFS_STATS 414 remove_proc_entry("Stats", proc_fs_cifs); 415#endif 416 remove_proc_entry("SecurityFlags", proc_fs_cifs); 417 remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); 418 remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); 419 remove_proc_entry("fs/cifs", NULL); 420} 421 422static int cifsFYI_proc_show(struct seq_file *m, void *v) 423{ 424 seq_printf(m, "%d\n", cifsFYI); 425 return 0; 426} 427 428static int cifsFYI_proc_open(struct inode *inode, struct file *file) 429{ 430 return single_open(file, cifsFYI_proc_show, NULL); 431} 432 433static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer, 434 size_t count, loff_t *ppos) 435{ 436 char c; 437 bool bv; 438 int rc; 439 440 rc = get_user(c, buffer); 441 if (rc) 442 return rc; 443 if (strtobool(&c, &bv) == 0) 444 cifsFYI = bv; 445 else if ((c > '1') && (c <= '9')) 446 cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */ 447 448 return count; 449} 450 451static const struct file_operations cifsFYI_proc_fops = { 452 .owner = THIS_MODULE, 453 .open = cifsFYI_proc_open, 454 .read = seq_read, 455 .llseek = seq_lseek, 456 .release = single_release, 457 .write = cifsFYI_proc_write, 458}; 459 460static int cifs_linux_ext_proc_show(struct seq_file *m, void *v) 461{ 462 seq_printf(m, "%d\n", linuxExtEnabled); 463 return 0; 464} 465 466static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file) 467{ 468 return single_open(file, cifs_linux_ext_proc_show, NULL); 469} 470 471static ssize_t cifs_linux_ext_proc_write(struct file *file, 472 const char __user *buffer, size_t count, loff_t *ppos) 473{ 474 char c; 475 bool bv; 476 int rc; 477 478 rc = get_user(c, buffer); 479 if (rc) 480 return rc; 481 482 rc = strtobool(&c, &bv); 483 if (rc) 484 return rc; 485 486 linuxExtEnabled = bv; 487 488 return count; 489} 490 491static const struct file_operations cifs_linux_ext_proc_fops = { 492 .owner = THIS_MODULE, 493 .open = cifs_linux_ext_proc_open, 494 .read = seq_read, 495 .llseek = seq_lseek, 496 .release = single_release, 497 .write = cifs_linux_ext_proc_write, 498}; 499 500static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v) 501{ 502 seq_printf(m, "%d\n", lookupCacheEnabled); 503 return 0; 504} 505 506static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file) 507{ 508 return single_open(file, cifs_lookup_cache_proc_show, NULL); 509} 510 511static ssize_t cifs_lookup_cache_proc_write(struct file *file, 512 const char __user *buffer, size_t count, loff_t *ppos) 513{ 514 char c; 515 bool bv; 516 int rc; 517 518 rc = get_user(c, buffer); 519 if (rc) 520 return rc; 521 522 rc = strtobool(&c, &bv); 523 if (rc) 524 return rc; 525 526 lookupCacheEnabled = bv; 527 528 return count; 529} 530 531static const struct file_operations cifs_lookup_cache_proc_fops = { 532 .owner = THIS_MODULE, 533 .open = cifs_lookup_cache_proc_open, 534 .read = seq_read, 535 .llseek = seq_lseek, 536 .release = single_release, 537 .write = cifs_lookup_cache_proc_write, 538}; 539 540static int traceSMB_proc_show(struct seq_file *m, void *v) 541{ 542 seq_printf(m, "%d\n", traceSMB); 543 return 0; 544} 545 546static int traceSMB_proc_open(struct inode *inode, struct file *file) 547{ 548 return single_open(file, traceSMB_proc_show, NULL); 549} 550 551static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer, 552 size_t count, loff_t *ppos) 553{ 554 char c; 555 bool bv; 556 int rc; 557 558 rc = get_user(c, buffer); 559 if (rc) 560 return rc; 561 562 rc = strtobool(&c, &bv); 563 if (rc) 564 return rc; 565 566 traceSMB = bv; 567 568 return count; 569} 570 571static const struct file_operations traceSMB_proc_fops = { 572 .owner = THIS_MODULE, 573 .open = traceSMB_proc_open, 574 .read = seq_read, 575 .llseek = seq_lseek, 576 .release = single_release, 577 .write = traceSMB_proc_write, 578}; 579 580static int cifs_security_flags_proc_show(struct seq_file *m, void *v) 581{ 582 seq_printf(m, "0x%x\n", global_secflags); 583 return 0; 584} 585 586static int cifs_security_flags_proc_open(struct inode *inode, struct file *file) 587{ 588 return single_open(file, cifs_security_flags_proc_show, NULL); 589} 590 591/* 592 * Ensure that if someone sets a MUST flag, that we disable all other MAY 593 * flags except for the ones corresponding to the given MUST flag. If there are 594 * multiple MUST flags, then try to prefer more secure ones. 595 */ 596static void 597cifs_security_flags_handle_must_flags(unsigned int *flags) 598{ 599 unsigned int signflags = *flags & CIFSSEC_MUST_SIGN; 600 601 if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) 602 *flags = CIFSSEC_MUST_KRB5; 603 else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) 604 *flags = CIFSSEC_MUST_NTLMSSP; 605 else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) 606 *flags = CIFSSEC_MUST_NTLMV2; 607 else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM) 608 *flags = CIFSSEC_MUST_NTLM; 609 else if (CIFSSEC_MUST_LANMAN && 610 (*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN) 611 *flags = CIFSSEC_MUST_LANMAN; 612 else if (CIFSSEC_MUST_PLNTXT && 613 (*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT) 614 *flags = CIFSSEC_MUST_PLNTXT; 615 616 *flags |= signflags; 617} 618 619static ssize_t cifs_security_flags_proc_write(struct file *file, 620 const char __user *buffer, size_t count, loff_t *ppos) 621{ 622 int rc; 623 unsigned int flags; 624 char flags_string[12]; 625 char c; 626 bool bv; 627 628 if ((count < 1) || (count > 11)) 629 return -EINVAL; 630 631 memset(flags_string, 0, 12); 632 633 if (copy_from_user(flags_string, buffer, count)) 634 return -EFAULT; 635 636 if (count < 3) { 637 /* single char or single char followed by null */ 638 c = flags_string[0]; 639 if (strtobool(&c, &bv) == 0) { 640 global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF; 641 return count; 642 } else if (!isdigit(c)) { 643 cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", 644 flags_string); 645 return -EINVAL; 646 } 647 } 648 649 /* else we have a number */ 650 rc = kstrtouint(flags_string, 0, &flags); 651 if (rc) { 652 cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", 653 flags_string); 654 return rc; 655 } 656 657 cifs_dbg(FYI, "sec flags 0x%x\n", flags); 658 659 if (flags == 0) { 660 cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string); 661 return -EINVAL; 662 } 663 664 if (flags & ~CIFSSEC_MASK) { 665 cifs_dbg(VFS, "Unsupported security flags: 0x%x\n", 666 flags & ~CIFSSEC_MASK); 667 return -EINVAL; 668 } 669 670 cifs_security_flags_handle_must_flags(&flags); 671 672 /* flags look ok - update the global security flags for cifs module */ 673 global_secflags = flags; 674 if (global_secflags & CIFSSEC_MUST_SIGN) { 675 /* requiring signing implies signing is allowed */ 676 global_secflags |= CIFSSEC_MAY_SIGN; 677 cifs_dbg(FYI, "packet signing now required\n"); 678 } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) { 679 cifs_dbg(FYI, "packet signing disabled\n"); 680 } 681 /* BB should we turn on MAY flags for other MUST options? */ 682 return count; 683} 684 685static const struct file_operations cifs_security_flags_proc_fops = { 686 .owner = THIS_MODULE, 687 .open = cifs_security_flags_proc_open, 688 .read = seq_read, 689 .llseek = seq_lseek, 690 .release = single_release, 691 .write = cifs_security_flags_proc_write, 692}; 693#else 694inline void cifs_proc_init(void) 695{ 696} 697 698inline void cifs_proc_clean(void) 699{ 700} 701#endif /* PROC_FS */ 702