12 Jun, 2009

1 commit

  • Move BKL into ->put_super from the only caller. A couple of
    filesystems had trivial enough ->put_super (only kfree and NULLing of
    s_fs_info + stuff in there) to not get any locking: coda, cramfs, efs,
    hugetlbfs, omfs, qnx4, shmem, all others got the full treatment. Most
    of them probably don't need it, but I'd rather sort that out individually.
    Preferably after all the other BKL pushdowns in that area.

    [AV: original used to move lock_super() down as well; these changes are
    removed since we don't do lock_super() at all in generic_shutdown_super()
    now]
    [AV: fuse, btrfs and xfs are known to need no damn BKL, exempt]

    Signed-off-by: Christoph Hellwig
    Signed-off-by: Al Viro

    Christoph Hellwig
     

09 May, 2009

1 commit


28 Apr, 2009

2 commits


23 Apr, 2009

2 commits

  • When using filename encryption with eCryptfs, the value of the symlink
    in the lower filesystem is encrypted and stored as a Tag 70 packet.
    This results in a longer symlink target than if the target value wasn't
    encrypted.

    Users were reporting these messages in their syslog:

    [ 45.653441] ecryptfs_parse_tag_70_packet: max_packet_size is [56]; real
    packet size is [51]
    [ 45.653444] ecryptfs_decode_and_decrypt_filename: Could not parse tag
    70 packet from filename; copying through filename as-is

    This was due to bufsiz, one the arguments in readlink(), being used to
    when allocating the buffer passed to the lower inode's readlink().
    That symlink target may be very large, but when decoded and decrypted,
    could end up being smaller than bufsize.

    To fix this, the buffer passed to the lower inode's readlink() will
    always be PATH_MAX in size when filename encryption is enabled. Any
    necessary truncation occurs after the decoding and decrypting.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     
  • This patch locks the lower directory inode's i_mutex before calling
    lookup_one_len() to find the appropriate dentry in the lower filesystem.
    This bug was found thanks to the warning set in commit 2f9092e1.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     

22 Apr, 2009

5 commits

  • A feature was added to the eCryptfs umount helper to automatically
    unlink the keys used for an eCryptfs mount from the kernel keyring upon
    umount. This patch keeps the unrecognized mount option warnings for
    ecryptfs_unlink_sigs out of the logs.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     
  • ecryptfs_passthrough is a mount option that allows eCryptfs to allow
    data to be written to non-eCryptfs files in the lower filesystem. The
    passthrough option was causing data corruption due to it not always
    being treated as a non-eCryptfs file.

    The first 8 bytes of an eCryptfs file contains the decrypted file size.
    This value was being written to the non-eCryptfs files, too. Also,
    extra 0x00 characters were being written to make the file size a
    multiple of PAGE_CACHE_SIZE.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     
  • The filename encryption key signature is not properly displayed in
    /proc/mounts. The "ecryptfs_sig=" mount option name is displayed for
    all global authentication tokens, included those for filename keys.

    This patch checks the global authentication token flags to determine if
    the key is a FEKEK or FNEK and prints the appropriate mount option name
    before the signature.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     
  • If data is NULL, msg_ctx->msg is set to NULL and then dereferenced
    afterwards. ecryptfs_send_raw_message() is the only place that
    ecryptfs_send_miscdev() is called with data being NULL, but the only
    caller of that function (ecryptfs_process_helo()) is never called. In
    short, there is currently no way to trigger the NULL pointer
    dereference.

    This patch removes the two unused functions and modifies
    ecryptfs_send_miscdev() to remove the NULL dereferences.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     
  • Copies the lower inode attributes to the upper inode before passing the
    upper inode to d_instantiate(). This is important for
    security_d_instantiate().

    The problem was discovered by a user seeing SELinux denials like so:

    type=AVC msg=audit(1236812817.898:47): avc: denied { 0x100000 } for
    pid=3584 comm="httpd" name="testdir" dev=ecryptfs ino=943872
    scontext=root:system_r:httpd_t:s0
    tcontext=root:object_r:httpd_sys_content_t:s0 tclass=file

    Notice target class is file while testdir is really a directory,
    confusing the permission translation (0x100000) due to the wrong i_mode.

    Signed-off-by: Tyler Hicks

    Tyler Hicks
     

21 Apr, 2009

1 commit


01 Apr, 2009

1 commit


28 Mar, 2009

1 commit


23 Mar, 2009

2 commits

  • If ecryptfs_encrypted_view or ecryptfs_xattr_metadata were being
    specified as mount options, a NULL pointer dereference of crypt_stat
    was possible during lookup.

    This patch moves the crypt_stat assignment into
    ecryptfs_lookup_and_interpose_lower(), ensuring that crypt_stat
    will not be NULL before we attempt to dereference it.

    Thanks to Dan Carpenter and his static analysis tool, smatch, for
    finding this bug.

    Signed-off-by: Tyler Hicks
    Acked-by: Dustin Kirkland
    Cc: Dan Carpenter
    Cc: Serge Hallyn
    Signed-off-by: Linus Torvalds

    Tyler Hicks
     
  • When allocating the memory used to store the eCryptfs header contents, a
    single, zeroed page was being allocated with get_zeroed_page().
    However, the size of an eCryptfs header is either PAGE_CACHE_SIZE or
    ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE (8192), whichever is larger, and is
    stored in the file's private_data->crypt_stat->num_header_bytes_at_front
    field.

    ecryptfs_write_metadata_to_contents() was using
    num_header_bytes_at_front to decide how many bytes should be written to
    the lower filesystem for the file header. Unfortunately, at least 8K
    was being written from the page, despite the chance of the single,
    zeroed page being smaller than 8K. This resulted in random areas of
    kernel memory being written between the 0x1000 and 0x1FFF bytes offsets
    in the eCryptfs file headers if PAGE_SIZE was 4K.

    This patch allocates a variable number of pages, calculated with
    num_header_bytes_at_front, and passes the number of allocated pages
    along to ecryptfs_write_metadata_to_contents().

    Thanks to Florian Streibelt for reporting the data leak and working with
    me to find the problem. 2.6.28 is the only kernel release with this
    vulnerability. Corresponds to CVE-2009-0787

    Signed-off-by: Tyler Hicks
    Acked-by: Dustin Kirkland
    Reviewed-by: Eric Sandeen
    Reviewed-by: Eugene Teo
    Cc: Greg KH
    Cc: dann frazier
    Cc: Serge E. Hallyn
    Cc: Florian Streibelt
    Cc: stable@kernel.org
    Signed-off-by: Linus Torvalds

    Tyler Hicks
     

15 Mar, 2009

1 commit

  • eCryptfs has file encryption keys (FEK), file encryption key encryption
    keys (FEKEK), and filename encryption keys (FNEK). The per-file FEK is
    encrypted with one or more FEKEKs and stored in the header of the
    encrypted file. I noticed that the FEK is also being encrypted by the
    FNEK. This is a problem if a user wants to use a different FNEK than
    their FEKEK, as their file contents will still be accessible with the
    FNEK.

    This is a minimalistic patch which prevents the FNEKs signatures from
    being copied to the inode signatures list. Ultimately, it keeps the FEK
    from being encrypted with a FNEK.

    Signed-off-by: Tyler Hicks
    Cc: Serge Hallyn
    Acked-by: Dustin Kirkland
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Tyler Hicks
     

07 Feb, 2009

1 commit

  • The addition of filename encryption caused a regression in unencrypted
    filename symlink support. ecryptfs_copy_filename() is used when dealing
    with unencrypted filenames and it reported that the new, copied filename
    was a character longer than it should have been.

    This caused the return value of readlink() to count the NULL byte of the
    symlink target. Most applications don't care about the extra NULL byte,
    but a version control system (bzr) helped in discovering the bug.

    Signed-off-by: Tyler Hicks
    Signed-off-by: Linus Torvalds

    Tyler Hicks
     

22 Jan, 2009

1 commit


07 Jan, 2009

10 commits

  • Arguments lower_dentry and ecryptfs_dentry in ecryptfs_create_underlying_file()
    have been merged into dentry, now fix it.

    Signed-off-by: Qinghuang Feng
    Cc: Randy Dunlap
    Cc: Michael Halcrow
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Qinghuang Feng
     
  • Flesh out the comments for ecryptfs_decode_from_filename(). Remove the
    return condition, since it is always 0.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • Kerneldoc updates for ecryptfs_parse_tag_70_packet().

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • Correct several format string data type specifiers. Correct filename size
    data types; they should be size_t rather than int when passed as
    parameters to some other functions (although note that the filenames will
    never be larger than int).

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • %Z is a gcc-ism. Using %z instead.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • Enable mount-wide filename encryption by providing the Filename Encryption
    Key (FNEK) signature as a mount option. Note that the ecryptfs-utils
    userspace package versions 61 or later support this option.

    When mounting with ecryptfs-utils version 61 or later, the mount helper
    will detect the availability of the passphrase-based filename encryption
    in the kernel (via the eCryptfs sysfs handle) and query the user
    interactively as to whether or not he wants to enable the feature for the
    mount. If the user enables filename encryption, the mount helper will
    then prompt for the FNEK signature that the user wishes to use, suggesting
    by default the signature for the mount passphrase that the user has
    already entered for encrypting the file contents.

    When not using the mount helper, the user can specify the signature for
    the passphrase key with the ecryptfs_fnek_sig= mount option. This key
    must be available in the user's keyring. The mount helper usually takes
    care of this step. If, however, the user is not mounting with the mount
    helper, then he will need to enter the passphrase key into his keyring
    with some other utility prior to mounting, such as ecryptfs-manager.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • Make the requisite modifications to ecryptfs_filldir(), ecryptfs_lookup(),
    and ecryptfs_readlink() to call out to filename encryption functions.
    Propagate filename encryption policy flags from mount-wide crypt_stat to
    inode crypt_stat.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • These functions support encrypting and encoding the filename contents.
    The encrypted filename contents may consist of any ASCII characters. This
    patch includes a custom encoding mechanism to map the ASCII characters to
    a reduced character set that is appropriate for filenames.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • Extensions to the header file to support filename encryption.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     
  • This patchset implements filename encryption via a passphrase-derived
    mount-wide Filename Encryption Key (FNEK) specified as a mount parameter.
    Each encrypted filename has a fixed prefix indicating that eCryptfs should
    try to decrypt the filename. When eCryptfs encounters this prefix, it
    decodes the filename into a tag 70 packet and then decrypts the packet
    contents using the FNEK, setting the filename to the decrypted filename.
    Both unencrypted and encrypted filenames can reside in the same lower
    filesystem.

    Because filename encryption expands the length of the filename during the
    encoding stage, eCryptfs will not properly handle filenames that are
    already near the maximum filename length.

    In the present implementation, eCryptfs must be able to produce a match
    against the lower encrypted and encoded filename representation when given
    a plaintext filename. Therefore, two files having the same plaintext name
    will encrypt and encode into the same lower filename if they are both
    encrypted using the same FNEK. This can be changed by finding a way to
    replace the prepended bytes in the blocked-aligned filename with random
    characters; they are hashes of the FNEK right now, so that it is possible
    to deterministically map from a plaintext filename to an encrypted and
    encoded filename in the lower filesystem. An implementation using random
    characters will have to decode and decrypt every single directory entry in
    any given directory any time an event occurs wherein the VFS needs to
    determine whether a particular file exists in the lower directory and the
    decrypted and decoded filenames have not yet been extracted for that
    directory.

    Thanks to Tyler Hicks and David Kleikamp for assistance in the development
    of this patchset.

    This patch:

    A tag 70 packet contains a filename encrypted with a Filename Encryption
    Key (FNEK). This patch implements functions for writing and parsing tag
    70 packets. This patch also adds definitions and extends structures to
    support filename encryption.

    Signed-off-by: Michael Halcrow
    Cc: Dustin Kirkland
    Cc: Eric Sandeen
    Cc: Tyler Hicks
    Cc: David Kleikamp
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     

06 Jan, 2009

3 commits

  • * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
    inotify: fix type errors in interfaces
    fix breakage in reiserfs_new_inode()
    fix the treatment of jfs special inodes
    vfs: remove duplicate code in get_fs_type()
    add a vfs_fsync helper
    sys_execve and sys_uselib do not call into fsnotify
    zero i_uid/i_gid on inode allocation
    inode->i_op is never NULL
    ntfs: don't NULL i_op
    isofs check for NULL ->i_op in root directory is dead code
    affs: do not zero ->i_op
    kill suid bit only for regular files
    vfs: lseek(fd, 0, SEEK_CUR) race condition

    Linus Torvalds
     
  • Fsync currently has a fdatawrite/fdatawait pair around the method call,
    and a mutex_lock/unlock of the inode mutex. All callers of fsync have
    to duplicate this, but we have a few and most of them don't quite get
    it right. This patch adds a new vfs_fsync that takes care of this.
    It's a little more complicated as usual as ->fsync might get a NULL file
    pointer and just a dentry from nfsd, but otherwise gets afile and we
    want to take the mapping and file operations from it when it is there.

    Notes on the fsync callers:

    - ecryptfs wasn't calling filemap_fdatawrite / filemap_fdatawait on the
    lower file
    - coda wasn't calling filemap_fdatawrite / filemap_fdatawait on the host
    file, and returning 0 when ->fsync was missing
    - shm wasn't calling either filemap_fdatawrite / filemap_fdatawait nor
    taking i_mutex. Now given that shared memory doesn't have disk
    backing not doing anything in fsync seems fine and I left it out of
    the vfs_fsync conversion for now, but in that case we might just
    not pass it through to the lower file at all but just call the no-op
    simple_sync_file directly.

    [and now actually export vfs_fsync]

    Signed-off-by: Christoph Hellwig
    Signed-off-by: Al Viro

    Christoph Hellwig
     
  • We used to have rather schizophrenic set of checks for NULL ->i_op even
    though it had been eliminated years ago. You'd need to go out of your
    way to set it to NULL explicitly _and_ a bunch of code would die on
    such inodes anyway. After killing two remaining places that still
    did that bogosity, all that crap can go away.

    Signed-off-by: Al Viro

    Al Viro
     

05 Jan, 2009

1 commit

  • With the write_begin/write_end aops, page_symlink was broken because it
    could no longer pass a GFP_NOFS type mask into the point where the
    allocations happened. They are done in write_begin, which would always
    assume that the filesystem can be entered from reclaim. This bug could
    cause filesystem deadlocks.

    The funny thing with having a gfp_t mask there is that it doesn't really
    allow the caller to arbitrarily tinker with the context in which it can be
    called. It couldn't ever be GFP_ATOMIC, for example, because it needs to
    take the page lock. The only thing any callers care about is __GFP_FS
    anyway, so turn that into a single flag.

    Add a new flag for write_begin, AOP_FLAG_NOFS. Filesystems can now act on
    this flag in their write_begin function. Change __grab_cache_page to
    accept a nofs argument as well, to honour that flag (while we're there,
    change the name to grab_cache_page_write_begin which is more instructive
    and does away with random leading underscores).

    This is really a more flexible way to go in the end anyway -- if a
    filesystem happens to want any extra allocations aside from the pagecache
    ones in ints write_begin function, it may now use GFP_KERNEL (rather than
    GFP_NOFS) for common case allocations (eg. ocfs2_alloc_write_ctxt, for a
    random example).

    [kosaki.motohiro@jp.fujitsu.com: fix ubifs]
    [kosaki.motohiro@jp.fujitsu.com: fix fuse]
    Signed-off-by: Nick Piggin
    Reviewed-by: KOSAKI Motohiro
    Cc: [2.6.28.x]
    Signed-off-by: KOSAKI Motohiro
    Signed-off-by: Andrew Morton
    [ Cleaned up the calling convention: just pass in the AOP flags
    untouched to the grab_cache_page_write_begin() function. That
    just simplifies everybody, and may even allow future expansion of the
    logic. - Linus ]
    Signed-off-by: Linus Torvalds

    Nick Piggin
     

01 Jan, 2009

1 commit

  • The result from readlink is being used to index into the link name
    buffer without checking whether it is a valid length. If readlink
    returns an error this will fault or cause memory corruption.

    Cc: Tyler Hicks
    Cc: Dustin Kirkland
    Cc: ecryptfs-devel@lists.launchpad.net
    Signed-off-by: Duane Griffin
    Acked-by: Michael Halcrow
    Acked-by: Tyler Hicks
    Signed-off-by: Al Viro

    Duane Griffin
     

04 Dec, 2008

1 commit


25 Nov, 2008

1 commit

  • The user_ns is moved from nsproxy to user_struct, so that a struct
    cred by itself is sufficient to determine access (which it otherwise
    would not be). Corresponding ecryptfs fixes (by David Howells) are
    here as well.

    Fix refcounting. The following rules now apply:
    1. The task pins the user struct.
    2. The user struct pins its user namespace.
    3. The user namespace pins the struct user which created it.

    User namespaces are cloned during copy_creds(). Unsharing a new user_ns
    is no longer possible. (We could re-add that, but it'll cause code
    duplication and doesn't seem useful if PAM doesn't need to clone user
    namespaces).

    When a user namespace is created, its first user (uid 0) gets empty
    keyrings and a clean group_info.

    This incorporates a previous patch by David Howells. Here
    is his original patch description:

    >I suggest adding the attached incremental patch. It makes the following
    >changes:
    >
    > (1) Provides a current_user_ns() macro to wrap accesses to current's user
    > namespace.
    >
    > (2) Fixes eCryptFS.
    >
    > (3) Renames create_new_userns() to create_user_ns() to be more consistent
    > with the other associated functions and because the 'new' in the name is
    > superfluous.
    >
    > (4) Moves the argument and permission checks made for CLONE_NEWUSER to the
    > beginning of do_fork() so that they're done prior to making any attempts
    > at allocation.
    >
    > (5) Calls create_user_ns() after prepare_creds(), and gives it the new creds
    > to fill in rather than have it return the new root user. I don't imagine
    > the new root user being used for anything other than filling in a cred
    > struct.
    >
    > This also permits me to get rid of a get_uid() and a free_uid(), as the
    > reference the creds were holding on the old user_struct can just be
    > transferred to the new namespace's creator pointer.
    >
    > (6) Makes create_user_ns() reset the UIDs and GIDs of the creds under
    > preparation rather than doing it in copy_creds().
    >
    >David

    >Signed-off-by: David Howells

    Changelog:
    Oct 20: integrate dhowells comments
    1. leave thread_keyring alone
    2. use current_user_ns() in set_user()

    Signed-off-by: Serge Hallyn

    Serge Hallyn
     

20 Nov, 2008

1 commit

  • I have received some reports of out-of-memory errors on some older AMD
    architectures. These errors are what I would expect to see if
    crypt_stat->key were split between two separate pages. eCryptfs should
    not assume that any of the memory sent through virt_to_scatterlist() is
    all contained in a single page, and so this patch allocates two
    scatterlist structs instead of one when processing keys. I have received
    confirmation from one person affected by this bug that this patch resolves
    the issue for him, and so I am submitting it for inclusion in a future
    stable release.

    Note that virt_to_scatterlist() runs sg_init_table() on the scatterlist
    structs passed to it, so the calls to sg_init_table() in
    decrypt_passphrase_encrypted_session_key() are redundant.

    Signed-off-by: Michael Halcrow
    Reported-by: Paulo J. S. Silva
    Cc: "Leon Woestenberg"
    Cc: Tim Gardner
    Cc:
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Michael Halcrow
     

14 Nov, 2008

2 commits

  • Pass credentials through dentry_open() so that the COW creds patch can have
    SELinux's flush_unauthorized_files() pass the appropriate creds back to itself
    when it opens its null chardev.

    The security_dentry_open() call also now takes a creds pointer, as does the
    dentry_open hook in struct security_operations.

    Signed-off-by: David Howells
    Acked-by: James Morris
    Signed-off-by: James Morris

    David Howells
     
  • Wrap access to task credentials so that they can be separated more easily from
    the task_struct during the introduction of COW creds.

    Change most current->(|e|s|fs)[ug]id to current_(|e|s|fs)[ug]id().

    Change some task->e?[ug]id to task_e?[ug]id(). In some places it makes more
    sense to use RCU directly rather than a convenient wrapper; these will be
    addressed by later patches.

    Signed-off-by: David Howells
    Reviewed-by: James Morris
    Acked-by: Serge Hallyn
    Cc: Mike Halcrow
    Cc: Phillip Hellewell
    Cc: ecryptfs-devel@lists.sourceforge.net
    Signed-off-by: James Morris

    David Howells
     

31 Oct, 2008

1 commit

  • When ecryptfs allocates space to write crypto headers into, before copying
    it out to file headers or to xattrs, it looks at the value of
    crypt_stat->num_header_bytes_at_front to determine how much space it
    needs. This is also used as the file offset to the actual encrypted data,
    so for xattr-stored crypto info, the value was zero.

    So, we kzalloc'd 0 bytes, and then ran off to write to that memory.
    (Which returned as ZERO_SIZE_PTR, so we explode quickly).

    The right answer is to always allocate a page to write into; the current
    code won't ever write more than that (this is enforced by the
    (PAGE_CACHE_SIZE - offset) length in the call to
    ecryptfs_generate_key_packet_set). To be explicit about this, we now send
    in a "max" parameter, rather than magically using PAGE_CACHE_SIZE there.

    Also, since the pointer we pass down the callchain eventually gets the
    virt_to_page() treatment, we should be using a alloc_page variant, not
    kzalloc (see also 7fcba054373d5dfc43d26e243a5c9b92069972ee)

    Signed-off-by: Eric Sandeen
    Acked-by: Michael Halcrow
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Eric Sandeen