Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cifs: try to handle the MUST SecurityFlags sanely

The cifs.ko SecurityFlags interface wins my award for worst-designed
interface ever, but we're sort of stuck with it since it's documented
and people do use it (even if it doesn't work correctly).

Case in point -- you can specify multiple sets of "MUST" flags. It makes
absolutely no sense, but you can do it.

What should the effect be in such a case? No one knows or seems to have
considered this so far, so let's define it now. If you try to specify
multiple MUST flags, clear any other MAY or MUST bits except for the
ones that involve signing.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>

authored by

Jeff Layton and committed by
Steve French
52dfb446 5d875cc9

+28
+28
fs/cifs/cifs_debug.c
··· 597 597 return single_open(file, cifs_security_flags_proc_show, NULL); 598 598 } 599 599 600 + /* 601 + * Ensure that if someone sets a MUST flag, that we disable all other MAY 602 + * flags except for the ones corresponding to the given MUST flag. If there are 603 + * multiple MUST flags, then try to prefer more secure ones. 604 + */ 605 + static void 606 + cifs_security_flags_handle_must_flags(unsigned int *flags) 607 + { 608 + unsigned int signflags = *flags & CIFSSEC_MUST_SIGN; 609 + 610 + if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) 611 + *flags = CIFSSEC_MUST_KRB5; 612 + else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) 613 + *flags = CIFSSEC_MUST_NTLMSSP; 614 + else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) 615 + *flags = CIFSSEC_MUST_NTLMV2; 616 + else if ((*flags & CIFSSEC_MUST_NTLM) == CIFSSEC_MUST_NTLM) 617 + *flags = CIFSSEC_MUST_NTLM; 618 + else if ((*flags & CIFSSEC_MUST_LANMAN) == CIFSSEC_MUST_LANMAN) 619 + *flags = CIFSSEC_MUST_LANMAN; 620 + else if ((*flags & CIFSSEC_MUST_PLNTXT) == CIFSSEC_MUST_PLNTXT) 621 + *flags = CIFSSEC_MUST_PLNTXT; 622 + 623 + *flags |= signflags; 624 + } 625 + 600 626 static ssize_t cifs_security_flags_proc_write(struct file *file, 601 627 const char __user *buffer, size_t count, loff_t *ppos) 602 628 { ··· 675 649 flags & ~CIFSSEC_MASK); 676 650 return -EINVAL; 677 651 } 652 + 653 + cifs_security_flags_handle_must_flags(&flags); 678 654 679 655 /* flags look ok - update the global security flags for cifs module */ 680 656 global_secflags = flags;