Apply upstream security patches from OpenAFS 1.6.7
* Apply upstream security patches:
- OPENAFS-SA-2014-001: Fix potential buffer overflow in the
fileserver. (CVE-2014-0159)
- Fix a potential DoS attack against Rx servers by avoiding suspending
the listener thread when delaying connection abort messages.
Andrew Deason [Wed, 10 Jul 2013 17:52:28 +0000 (12:52 -0500)]
Reload rxkad.keytab on CellServDB modification
Make the reloading of rxkad.keytab keys occur in the same way that
KeyFile keys are reloaded. That is, we only try to reload them if the
CellServDB mtime has changed. This is intended to have exactly the
same reloading behavior as KeyFile reloads.
I would have triggered this from afsconf_Check, but that approach
has annoyances. (Calling ticket5_keytab functions directly from
cellconfig pulls in libkrb5 dependencies for everything that uses
cellconfig, and we'd have to trigger an afsconf_Check call by calling
some other cellconfig function.)
Andrew Deason [Mon, 10 Jun 2013 22:49:12 +0000 (17:49 -0500)]
Avoid calling afsconf_GetLatestKey directly
Don't call afsconf_GetLatestKey to determine whether we can print our
own local tokens, since we may have keytab 'local' keys, but no DES
keys. Just try to construct them and see if it fails, using
afsconf_PickClientSecObj or afsconf_ClientAuth{,Secure} as
appropriate.
Andrew Deason [Mon, 10 Jun 2013 22:15:27 +0000 (17:15 -0500)]
auth: Do not always fallback to noauth
Make afsconf_PickClientSecObj error out if we can't construct
localauth tokens (unless the caller explicitly requested rxnull
fallback). afsconf_ClientAuth{,Secure} still falls back, as always.
Ben Kaduk [Tue, 14 May 2013 23:37:59 +0000 (19:37 -0400)]
Clean up akimpersonate and use for server-to-server
Since a6d7cacfd, aklog has been able to print a krb5 ticket to
itself for an arbitrary client principal, allowing a user with
access to the cell's krb5 key to get tokens as an arbitrary user.
Now that it is possible to use native krb5 tickets with non-DES
enctypes for authentication, and akimpersonate is available from libauth,
use printed native krb5 tickets for server-to-server communication (as well
as the -localauth versions of the client utilities).
Remove the early call to afsconf_GetLatestKey() in
afsconf_PickClientSecObj() so that we do not end up picking an old DES
key before we try to find a better key to use.
Before doing so, refactor the akimpersonate code to be more usable
and readable, and eliminate some dead code. For example, we always printed
addressless tickets, so that code could be removed. Other code had excessive
stack usage for a library routine, which is eliminated. Use a start time
of 0 instead of 300 so that the printed ticket will always be
detected as infinite-lifetime.
In order to ensure usability on all platforms (in particular Solaris),
provide a couple more compat shims to implement routines which are not
always available from the krb5 library, in particular encode_krb5_ticket
and encode_krb5_enc_tkt_part. Thanks to Andrew Deason for implementing
these compatability routines.
Give it its own source file and header, install the header at
depinstall time, and have aklog get the akimpersonate functionality
from libauth.
Keep the linux box copyright from aklog_main.c (but strip the trailing
whitespace), as that block was added with the akimpersonate code.
Remove all calls to afs_com_err() as is fitting for library code,
to let it build. Do not bother removing curly braces which are
no longer needed; a future cleanup commit will catch that.
Derive DES/fcrypt session key from other key types
If a kerberos 5 ticket has a session key with a non-DES enctype,
use the NIST SP800-108 KDF in counter mode with HMAC_MD5 as the PRF to
construct a DES key to be used by rxkad.
To satisfy the requirements of the KDF, DES3 keys are first compressed into a
168 bit form by reversing the RFC3961 random-to-key algorithm
New optional rxkad functionality for decypting krb5 tokens
An additional, optional mechanism for decrypting krb5-format tokens
is provided that uses the krb5 api with a key from a keytab
instead of using libdes and the AFS KeyFile.
The AIX compat stub for krb5_c_decrypt is contributed by Andrew Deason.
Add rxkad server hook function to decrypt more types of tokens
Allow tokens to be encrypted with algorithms other than DES.
The security object owner must provide an implementation
by calling rxkad_SetAltDecryptProc.
Make sure plainsiz is initialized before calling the alternate decrypt
proc.
Russ Allbery [Sun, 24 Feb 2013 22:58:11 +0000 (14:58 -0800)]
OpenAFS-SA-2013-0002: Buffer overflow in OpenAFS ptserver
The ptserver accepts a list of unbounded size from the IdToName RPC. The
length of this list is then used to determine the size of a number of other
internal datastructures. If the length is sufficiently large then we may
hit an integer overflow when calculating the size to pass to malloc, and
allocate data structures of insufficient length, allowing heap memory to
be overwritten.
Russ Allbery [Sun, 24 Feb 2013 22:56:54 +0000 (14:56 -0800)]
OpenAFS-SA-2013-0001: Buffer overflow in OpenAFS fileserver
By carefully crafting an ACL entry an attacker may overflow fixed length
buffers within the OpenAFS fileserver, crashing the fileserver, and
potentially permitting the execution of arbitrary code. To perform the
exploit, the attacker must already have permissions to create ACLs on the
fileserver in question.
Once such an ACL is present on a fileserver, client utilities such as 'fs'
which manipulate ACLs, may be crashed when they attempt to read or modify
the ACL.
This change causes issues as-is for users who are not experiencing the
reconnect bug, and when investigation is complete a corrected version
will be included in a future release.
Andrew Deason [Fri, 2 Mar 2012 20:55:04 +0000 (14:55 -0600)]
viced: Do not ignore all InlineBulkStatus errors
InlineBulkStatus currently returns 0 unconditionally, no matter what
errors are encountered. If we encounter an error early enough, from
CallPreamble for example, we do not fill in the OutStats nor CallBacks
structures at all. Since we return success anyway, this results in the
client getting AFSFetchStatus structures full of zeroes (or garbage,
before commit 726e1e13ff93e2cc1ac21964dc8d906869e64406).
Since current OpenAFS clients do not perform any sanity checks on the
information received, this can result in cache corruption of files
being seen incorrectly as empty, and, before commit 726e1e, more
arbitrary corruption.
So instead, return an error if we encounter an error before we iterate
over the given FIDs. We still of course do not return an error for any
errors encountered during the actual metadata retrieval, as those are
reflected in the individual per-fid status structures.
OpenAFS changed the behavior of implicit administrator permission
for directory ownership. In OpenAFS only the volume root directory
owner has implicit administrator permissions and they apply to all
directories in the volume not just those with matching ownership.
Andrew Deason [Wed, 22 Feb 2012 21:40:20 +0000 (15:40 -0600)]
LINUX: Use afs_convert_code in afs_notify_change
afs_notify_change currently just returns "-code". This can cause a
panic if the error code is negative, since we will return a positive
error code, which may get interpreted as a valid pointer value in
higher levels.
Specifically, if we hit afs_notify_change via something like this code
path:
Andrew Deason [Wed, 22 Feb 2012 21:36:37 +0000 (15:36 -0600)]
LINUX: move afs_notify_change to osi_vnodeops.c
afs_notify_change is almost always used solely in inode_operations
structs, and is more similar to the other per-vnode functions. Put it
with the other per-vnode functions for better organization, and so
they can use the same static functions.
Move the helper functions iattr2vattr and vattr2inode along with it.
Jeffrey Altman [Thu, 22 Mar 2012 19:55:47 +0000 (15:55 -0400)]
Windows: Client handling of VNOSERVICE
VNOSERVICE should not be grouped together with the volume status
error codes. It is used to indicate that the RPC was not serviced.
The file server issues it when its idle dead timeout period is reached
while receiving rx call data. The client's existing status information
is still valid and the client can retry the call.
Andrew Deason [Wed, 7 Mar 2012 22:36:57 +0000 (16:36 -0600)]
afs: Never #define away afsd_dynamic_vcaches
Some versions of the Solaris Studio compiler on SPARC (at least 12.2
and possibly others, but not 12.3) get a little confused by code like
this:
extern int foo;
int
somefunc(void) {
if (0) return foo;
return 0;
}
When optimization is turned off, this results in an undefined symbol
reference to 'foo' (which is normal), but the resulting object file
lacks a relocation entry for the symbol 'foo', so the symbol remains
undefined after linking. In the OpenAFS tree, this occurs in
afs_daemons.c which references afs_vcount and afs_cacheStats in this
manner due to afsd_dynamic_vcaches being defined as '0' on Solaris.
The end result is that the libafs kernel module is not loadable, since
it complains about afs_vcount and afs_cacheStats being undefined, even
though the symbol definitions are also in the module.
While this is a bug in Solaris Studio and has since been fixed, it is
simple to work around this so we are usable with more compilers. If we
just always declare afsd_dynamic_vcaches as a regular variable, it
works around this issue and keeps the code a tiny bit simpler. So, do
that.
Reviewed-on: http://gerrit.openafs.org/6888 Tested-by: Michael Meffie <mmeffie@sinenomine.net> Reviewed-by: Michael Meffie <mmeffie@sinenomine.net> Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit e5821239cde138f74f73bec1bd9a3880d08ac3df)
Simon Wilkinson [Wed, 14 Mar 2012 14:56:06 +0000 (10:56 -0400)]
rx: hold call->lock across RXS_PreparePacket
RX Security Classes have a right to assume that when RXS_PreparePacket
is called that they have exclusive access to the rx_call structure.
Commit e445faa68c5ec6e47d3fd9d7318ade71d98703a9 unintentionally
failed to acquire the call->lock prior to RXS_PreparePacket being
called.
When using an unadorned %config, it's possible that these files will
be replaced by the packaged version during a package update. Changing
%config to %config(noreplace) means that the packaged file will be
installed with the extension .rpmnew if there is already a modified
(from the existing package's version) file with the same name on the
installed machine.
The concern here is that updating an existing system could potentially
change the configuration if the person installing doesn't pay close
attention. The Rule of Least Surprise indicates that we should
try to preserve existing configuration changes whenever possible.
Dave Botsch [Thu, 1 Mar 2012 17:43:36 +0000 (12:43 -0500)]
Fixes dkms.conf for Redhat Enterprise
commit 8e0aaae076f4cccfd2d6ed81ede4e355235b578e , while fixing dkms.conf for
Fedora, broke dkms.conf for RHEL. In RHEL, you get a dkms.conf with too
many backslashes in the "mv" line. The dkms.conf should have the mv line
reading:
mv src/libafs/MODLOAD-*/\$KMODNAME \$DSTKMOD"
for Fedora.
This change checks if we are building on Fedora, and if so, maintains
the extra backslashes. Otherwise, not.
modified: src/packaging/RedHat/openafs.spec.in
Uses the dist tags as specified at
http://fedoraproject.org/wiki/Packaging:DistTag
Reviewed-on: http://gerrit.openafs.org/6851 Reviewed-by: Ken Dreyer <ktdreyer@ktdreyer.com> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit 81a9a33e0bc5455841ba105dab52735c64c7096b)
Jeffrey Altman [Thu, 1 Mar 2012 20:49:12 +0000 (15:49 -0500)]
unix: always retry RX_CALL_BUSY
RX_CALL_BUSY is an indication that the call channel is busy not
that the server is down or otherwise cannot respond. Unconditionally
retry the RPC and do not alter state. We just want to force the use
of a different call channel.
Jeffrey Altman [Wed, 29 Feb 2012 18:07:47 +0000 (13:07 -0500)]
Windows: Workaround Win7 SMB Reconnect Bug
The SMB specification permits the server to save a round trip
in the GSS negotiation by sending an initial security blob.
Unfortunately, doing so trips a bug in Windows 7 and Server 2008 R2
whereby the SMB 1.x redirector drops the blob on the floor after
the first connection to the server and simply attempts to reuse
the previous authentication context. This bug can be avoided by
the server sending no security blob in the SMB_COM_NEGOTIATE
response. This forces the client to send an initial GSS init_sec_context
blob under all circumstances which works around the bug in Microsoft's
code.
Do not call smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
As a result of the SMB 1.x bug, all attempts to reconnect fail due to
SMB connection resets. The SMB 1.x redirector will retry indefinitely
but all processes with outstanding requests to \\AFS will block until
the machine is rebooted.
Jeffrey Altman [Sun, 26 Feb 2012 19:45:43 +0000 (14:45 -0500)]
Windows: disable Adv ICF support if not supported
OpenAFS 1.6.x does not require the use of SDK 6.0 or above.
Therefore the Advanced Internet Connection Firewall support
may not be available. In particular, the 32-bit distribution
for 1.6.x does not rely on SDK 6.0 or higher.
Jeffrey Altman [Wed, 18 Jan 2012 00:46:30 +0000 (19:46 -0500)]
Windows: failover and retry for VBUSY
When a file server returns the VBUSY error for an RPC the
cache manager records the 'srv_busy' state in the cm_serverRef_t
structure binding that file server to the active cm_volume_t
object. The 'srv_busy' was never cleared which prevents the
volume from being accessed.
Clear the 'srv_busy' flag whenever cm_Analyze() receives a
CM_ERROR_ALLBUSY error which means that all replicas have
been tried or whenever the error is not VBUSY or VRESTARTING.
Jeffrey Altman [Fri, 25 Nov 2011 14:28:18 +0000 (09:28 -0500)]
Windows: improved idle dead time handling
RX_CALL_IDLE has been treated the same as RX_CALL_DEAD which is
a fatal error that results in the server being marked down. This
is not the appropriate behavior for an idle dead timeout error
which should not result in servers being marked down.
Idle dead timeouts are locally generated and are an indication
that the server:
a. is severely overloaded and cannot process all
incoming requests in a timely fashion.
b. has a partition whose underlying disk (or iSCSI, etc) is
failing and all I/O requests on that device are blocking.
c. has a large number of threads blocking on a single vnode
and cannot process requests for other vnodes as a result.
d. is malicious.
RX_CALL_IDLE is distinct from RX_DEAD_CALL in that idle dead timeout
handling should permit failover to replicas when they exist in a
timely fashion but in the non-replica case should not be triggered
until the hard dead timeout. If the request cannot be retried, it
should fail with an I/O error. The client should not retry a request
to the same server as a result of an idle dead timeout.
In addition, RX_CALL_IDLE indicates that the client has abandoned
the call but the server has not. Therefore, the client cannot determine
whether or not the RPC will eventually succeed and it must discard
any status information it has about the object of the RPC if the
RPC could have altered the object state upon success.
This patchset splits the RX_CALL_DEAD processing in cm_Analyze() to
clarify that only RX_CALL_DEAD errors result in the server being marked
down. Since Rx idle dead timeout processing is per connection and
idle dead timeouts must differ depending upon whether or not replica
sites exist, cm_ConnBy*() are extended to select a connection based
upon whether or not replica sites exist. A separate connection object
is used for RPCs to replicated objects as compared to RPCs to non-replicated
objects (volumes or vldb).
For non-replica connections the idle dead timeout is set to the hard
dead timeout. For replica connections the idle dead timeout is set
to the configured idle dead timeout.
Idle dead timeout events and whether or not a retry was triggered
are logged to the Windows Event Log.
cm_Analyze() is given a new 'storeOp' parameter which is non-zero
when the execute RPC could modify the data on the file server.
Jeffrey Altman [Fri, 3 Feb 2012 16:21:45 +0000 (11:21 -0500)]
Windows: fix cm_DirOpDelBuffer assert
In cm_DirOpDelBuffer() the data version field for a buffer
in cm_dirOp_t.buffers[] can be CM_BUF_VERSION_BAD if the buffer
was added to the buffer list but was never fetched from the file
server. If the buffer was recycled by buf_Get() an attempt to
remove an entry from the directory will be failed as opposed to
fetching the buffer from the file server and performing the local
removal.
Jeffrey Altman [Fri, 3 Feb 2012 16:17:40 +0000 (11:17 -0500)]
Windows: buffer DV ranges do not work for directories
In cm_MergeStatus, always set cm_scache_t.bufDataVersionLow
to the new data version because the cm_dir package does not
support version ranges. All modified dir buffers have their
dataVersion field set to the current data version value.
Failure to update the bufDataVersionLow field can result in
B+ Trees being constructed from out of date directory information.
Jeffrey Altman [Sun, 22 Jan 2012 23:33:43 +0000 (18:33 -0500)]
Windows; release BIOD after status merge
Releasing the BIOD permits the accumulated buffers to be accessed.
Releasing the BIOD before the cm_MergeStatus() call creates a
window where the buffer data version is larger than the cm_scache
data version. Release the BIOD after the status merge.
Jeffrey Altman [Thu, 19 Jan 2012 20:25:44 +0000 (15:25 -0500)]
Windows: cm_buf refcnt must hold buf_globalLock
An assertion in buf_Recycle() was being triggered when a cm_buf_t
object was supposed to be in the free buffer list but wasn't.
buf_Recycle() was racing with another thread. The test for
refCount == 0 was performed while holding the buf_globalLock
exclusively but the InterlockedDecrement(refCount) in buf_Release()
was performed without holding buf_globalLock at all. buf_globalLOck
must be held at least as a read lock. Otherwise, the refCount can
reach 0 prior to the thread blocking for exclusive access to the
buf_globalLock. This provides buf_Recycle() which is holding
buf_globalLock the opportunity to race.
The solution is to make sure that buf_Release() always holds
buf_globalLock as a read lock and then use buf_ReleaseLocked()
to perform the actual decrement and test.
Jeffrey Altman [Sat, 14 Jan 2012 15:31:01 +0000 (10:31 -0500)]
Windows: restrict service to 2 cpus by default
Performance drops off considerably when the number of processors
increases due to lock contention and the cm_SyncOp wait processing.
If the MaxCPUs registry value is not set, limit ourselves to two.
Setting MaxCPUs to zero permits use of all CPUs.
Jeffrey Altman [Sat, 24 Dec 2011 08:11:04 +0000 (03:11 -0500)]
Windows: cm_BufWrite() must wait in cm_SyncOp()
Now that it is permissible for more than one store data operation
to construct BIOD lists in parallel, cm_BufWrite() must be willing
to wait in cm_SyncOp(). Otherwise, the daemon threads will spin.
Jeffrey Altman [Sat, 3 Dec 2011 22:49:47 +0000 (17:49 -0500)]
Windows: apply Nat Pings only to cm_rootUser connections
Use CM_UCELLFLAG_ROOTUSER flag to identify the cm_rootUser
connections and only apply Nat pings to those connections
instead of examining the security state of the connection.
Jeffrey Altman [Fri, 2 Dec 2011 16:14:11 +0000 (11:14 -0500)]
Windows: buf_CleanAsync is not async; rename it
buf_CleanAsync() calls cm_BufWrite() which stores the dirty
buffers synchronously. There is nothing asynchronous about
buf_CleanAsync() so rename it to buf_Clean() and buf_CleanAsyncLocked()
to buf_CleanLocked(). Update the comments to remove the references
to the asynchronous processing which doesn't exist.
That is not to say that the call to buf_Clean() in buf_GetNewLocked()
should not be asynchronous; it should. There is no such functionality
at the moment. One approach would be to modify buf_IncrSyncer to
trigger on an event set by buf_GetNewLocked() instead of the call
to buf_Clean(). Another approach would be registering a background
store event. In any case, that is for another patchset.
Jeffrey Altman [Mon, 21 Nov 2011 18:14:40 +0000 (13:14 -0500)]
Windows: cm_GetSCache do not release unheld lock
if cm_GetNewSCache() fails, an attempt would be made to
release cm_scacheLock which is not held. However, it should
be noted that cm_GetNewSCache() cannot fail without itself
triggering a panic.
Jeffrey Altman [Tue, 15 Nov 2011 23:35:26 +0000 (18:35 -0500)]
Windows: buf_CleanAsyncLocked dirty range only
buf_CleanAsyncLocked() should not instruct cm_BufWrite() to
write a full chunk if the current buffer is the only one that
is dirty. cm_BufWrite() will determine if it is appropriate
to fill a full chunk when storing. Instructing it to check
a full chunk forces it to do more work than necessary.
Jeffrey Altman [Wed, 16 Nov 2011 00:00:05 +0000 (19:00 -0500)]
Windows: cm_SetupStoreBIOD use firstModOffset chunk
When cm_SetupStoreBIOD attempts to store a chunk to the file
server it should not use *inOffsetp as the start of the range.
There is no guarantee that the buffer at *inOffsetp is dirty.
Instead use firstModOffset which refers to the first known
dirty buffer in the range specified by the caller. Attempt
to fill a chunk of consecutive dirty buffers from that point.
smb_ReceiveNTCreateX() calls cm_CheckNTOpen() which now
requires the smb_fid_t allocated fid value for use in share
mode locking. Move the allocation of the smb_fid earlier
in the function and apply necessary cleanup in error paths.
Jeffrey Altman [Sat, 12 Nov 2011 18:41:30 +0000 (13:41 -0500)]
Windows: fix locking hierarchy in service
The smb username lock and the daemon global lock can be requested
while the scache dirlock is held if there are no free buffers
and the service is forced to claw back extents from the redirector.
Adjust the locking hierarchy accordingly.
Jeffrey Altman [Sun, 28 Aug 2011 16:03:53 +0000 (12:03 -0400)]
Windows: afslogon network provider debug registry value
create a new TransarcAFSDaemon\NetworkProvider "Debug" value
to be used for activating the network provider debugging.
The overlapping use of TransarcAFSDaemon\Parameters "TraceOption"
is just too confusing.
Jeffrey Altman [Fri, 26 Aug 2011 17:57:15 +0000 (13:57 -0400)]
Windows: afslogon.dll is not a file system interface
Do not return a file system network type that corresponds
to a real file system inter since afslogon is in fact not
associated with a file system interface. We can't return
WNNC_NET_NONE (0) because that prevents NPLogonNotify()
from being executed. However, if we return an in use
file system value that can confuse the system when the
actual file system's network provider is also installed.
Jeffrey Altman [Fri, 26 Aug 2011 13:36:04 +0000 (09:36 -0400)]
Windows: torture error reporting
When LeaveThread() is called and GetLastError() has already
been called, pass the last error value to LeaveThread(). Otherwise,
the GetLastError() call in LeaveThread() may return an inaccurrate
result.
Jeffrey Altman [Tue, 23 Aug 2011 20:02:28 +0000 (16:02 -0400)]
Windows: change buf_Find*() signature to accept cm_fid_t
The buf_Find*() functions require a cm_fid_t to match with the
cm_buf_t objects not a cm_scache_t. Change the signature so
that the cm_scache_t is not required. It should be possible to
search for a buffer even if the cm_scache_t is not present in
the cache.
Jeffrey Altman [Fri, 19 Aug 2011 01:57:12 +0000 (21:57 -0400)]
Windows: be explicit when mapping sharing violation
Only one lock acquistion failure should be mapping to
CM_ERROR_SHARING_VIOLATION. That is CM_ERROR_LOCK_NOT_GRANTED.
Make it clear that is what we are doing.
Jeffrey Altman [Tue, 9 Aug 2011 18:26:33 +0000 (14:26 -0400)]
Windows: avoid duplicate volume update queries
If multiple volume update queries have stacked up in
cm_UpdateVolumeLocation() and the active query failed,
do not re-issued the blocked queries. Instead, prevent new
queries for 60 seconds and fail those that blocked during
the active query.
Andrew Deason [Fri, 24 Feb 2012 00:28:21 +0000 (18:28 -0600)]
Rewrite make_h_tree.pl in shell script
The current usage of make_h_tree.pl adds a build requirement of
/usr/bin/perl that we did not have prior to commit 1d6593e952ce82c778b1cd6e40c6e22ec756daf1. Do the same thing in a
bourne shell script instead, so we don't need perl.
Note that this is not as generalized as make_h_tree.pl, but it doesn't
need to be. Specifically, this does not strip a leading ../ from found
include directives (nothing in the tree that includes h/* files uses
this), and header filenames containing whitespace almost certainly do
not work correctly.
The h => sys mapping is also much more hardcoded, but that's all we
were using this for anyway.