The branch, v4-9-stable has been updated via ba2ef7f VERISON: Disable GIT_SNAPSHOT for 4.9.0rc3 release. via 6f1fdf9 WHATSNEW: Add release notes for Samba 4.9.0rc3. via bf3bb82 libsmb: Fix CID 1438243 Unchecked return value via 601eb6b libsmb: Fix CID 1438244 Unsigned compared against 0 via 33c7d3c smbd: Fix CID 1438245 Dereference before null check via 0eaef7e smbd: Fix CID 1438246 Unchecked return value via e30cf1a smbd: Align integer types via 2d5c574 ctdb: add expiry test for ctdb_mutex_ceph_rados_helper via 37b4e0b ctdb_mutex_ceph_rados_helper: fix deadlock via lock renewals via 2849d57 ctdb_mutex_ceph_rados_helper: rename timer_ev to ppid_timer_ev via 5f3548b ctdb_mutex_ceph_rados_helper: use talloc destructor for cleanup via eae828b ctdb_mutex_ceph_rados_helper: Set SIGINT signal handler via 609109d ctdb/build: link ctdb_mutex_ceph_rados_helper against ceph-common via b09fdd0 s3: tests: smbclient. Regression test to ensure we get NT_STATUS_DIRECTORY_NOT_EMPTY on rmdir. via 921a5bb s4/torture: Add new test for DELETE_ON_CLOSE on non-empty directories via 81b0d5c s3/libsmb: Explicitly set delete_on_close token for rmdir via 7ed470b cracknames: Fix DoS (NULL pointer de-ref) when not servicePrincipalName is set on a user via 4a2880b libsmb: Harden smbc_readdir_internal() against returns from malicious servers. via 61e34a2 libsmb: Ensure smbc_urlencode() can't overwrite passed in buffer. via 4897bf3 CVE-2018-10919 tests: Add extra test for dirsync deleted object corner-case via 52b5ed8 CVE-2018-10919 acl_read: Fix unauthorized attribute access via searches via a5cd47d CVE-2018-10919 acl_read: Flip the logic in the dirsync check via 4c201d0 CVE-2018-10919 acl_read: Small refactor to aclread_callback() via 0395055 CVE-2018-10919 acl_read: Split access_mask logic out into helper function via 605a7f3 CVE-2018-10919 security: Fix checking of object-specific CONTROL_ACCESS rights via 9c9f50b CVE-2018-10919 tests: test ldap searches for non-existent attributes. via e2574d0 CVE-2018-10919 tests: Add test case for object visibility with limited rights via 10a2c8d CVE-2018-10919 tests: Add tests for guessing confidential attributes via 17b7206 CVE-2018-10919 security: Add more comments to the object-specific access checks via 5bcbf5a CVE-2018-10919 security: Move object-specific access checks into separate function via 164766b CVE-2018-1140 dns: Add a test to trigger the LDB casefolding issue on invalid chars via e2d6ad5 Release LDB 1.4.2 for CVE-2018-1140 via bf988ac CVE-2018-1140 ldb: Add tests for search add and rename with a bad dn= DN via dc2898f CVE-2018-1140 ldb_tdb: Check for DN validity in add, rename and search via 8fed2cc CVE-2018-1140 ldb_tdb: Ensure the dn in distinguishedName= is valid before use via 504cff7 CVE-2018-1140 ldb: Check for ldb_dn_get_casefold() failure in ldb_sqlite via 31a001f CVE-2018-1140 Add NULL check for ldb_dn_get_casefold() in ltdb_index_dn_attr() via 3e89172 CVE-2018-1139 libcli/auth: Do not allow ntlmv1 over SMB1 when it is disabled via "ntlm auth". via e2b2c00 CVE-2018-1139 selftest: verify whether ntlmv1 can be used via SMB1 when it is disabled. via 48f5dbd CVE-2018-1139 s3-utils: use enum ntlm_auth_level in ntlm_password_check(). via d171f8d CVE-2018-1139 libcli/auth: fix debug messages in hash_password_check() via 3579ac4 CVE-2018-1139 libcli/auth: Add initial tests for ntlm_password_check() via 7751937 s3/smbd: Ensure quota code is only called when quota support detected via 31e07eb Shorten description in vfs_linux_xfs_sgid manual via 1a0d142 s3:waf: Install eventlogadm to /usr/sbin via b1558f1 systemd: Only start smb when network interfaces are up via 39dc0db ctdb-eventd: Fix CID 1438155 via ec22496 ctdb: Fix a cut&paste error via b0c0a19 s3/utils: fix regression where specifying -Unetbios/root works via 134f17c s3/smbd: allow set quota for non root user (when built with --enable-selftest) via 951722d s3/script/tests: Add simple (smb1 & smb2) get/set/list tests for smbcquotas via a9d0df4 s3/script/test: modify existing smbcquota test to use SMB2 in addition to SMB1. via b65c3de s3/smbd: smb2 server implementation for query get/set info. via 046d3a3 s3/smbd: adjust smb1 server to use idl structs and generated ndr push/pull funcs via bdfcecc s3/libsmb: adjust smb2 code for new idl structs & generated ndr push/pull funcs. via 0ccd34a s3/libsmb: adjust smb1 cli code to use idl structs and ndr push/pull funcs. via 59bb7dd librpc/idl Add some query [getset]info quota related structures via 6c24eae s3/smbd: Don't stat when doing a quota operation (as it's a fake file) via 1d7b1dc s3/libsmb: Avoid potential smbpanic calling parse_user_quota_list. via 8b98831 s3/lib: Fix misleading typo in debug message via 6b5e4a7 s3-tldap: do not install test_tldap via 7894067 VERSION: Bump version up to 4.9.0rc3... from 7f744ab VERSION: Disable GIT_SNAPSHOT for the 4.9.0rc2 release.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-9-stable - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- WHATSNEW.txt | 61 +- ctdb/common/path.c | 2 +- ctdb/event/event_tool.c | 2 +- ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c | 200 +++- ctdb/utils/ceph/test_ceph_rados_reclock.sh | 57 +- ctdb/wscript | 14 +- docs-xml/manpages/vfs_linux_xfs_sgid.8.xml | 2 +- lib/ldb/ABI/{ldb-1.4.1.sigs => ldb-1.4.2.sigs} | 0 ...b-util.py3-1.4.1.sigs => pyldb-util-1.4.2.sigs} | 0 ...il.py3-1.4.1.sigs => pyldb-util.py3-1.4.2.sigs} | 0 lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 3 + lib/ldb/ldb_tdb/ldb_index.c | 18 + lib/ldb/ldb_tdb/ldb_search.c | 16 + lib/ldb/ldb_tdb/ldb_tdb.c | 27 +- lib/ldb/tests/python/api.py | 156 +++ lib/ldb/wscript | 2 +- libcli/auth/ntlm_check.c | 10 +- libcli/auth/tests/ntlm_check.c | 413 ++++++++ libcli/auth/wscript_build | 13 + libcli/security/access_check.c | 110 ++- librpc/idl/quota.idl | 54 ++ librpc/idl/wscript_build | 1 + librpc/wscript_build | 5 + packaging/systemd/smb.service.in | 3 +- python/samba/tests/dns_invalid.py | 87 ++ selftest/knownfail | 3 +- selftest/target/Samba3.pm | 9 + selftest/tests.py | 2 + source3/lib/sysquotas.c | 2 +- source3/libsmb/cli_smb2_fnum.c | 99 +- source3/libsmb/cliquota.c | 399 ++++---- source3/libsmb/libsmb_dir.c | 57 +- source3/libsmb/libsmb_path.c | 9 +- source3/libsmb/proto.h | 6 + source3/script/tests/getset_quota.py | 154 +++ source3/script/tests/test_dfree_quota.sh | 14 +- source3/script/tests/test_smbclient_s3.sh | 42 + source3/script/tests/test_smbcquota.py | 244 +++++ .../script/tests/test_smbcquota.sh | 42 +- source3/selftest/tests.py | 3 +- source3/smbd/nttrans.c | 669 +++++++------ source3/smbd/proto.h | 14 + source3/smbd/smb2_getinfo.c | 87 +- source3/smbd/smb2_setinfo.c | 41 + source3/smbd/trans2.c | 3 +- source3/utils/ntlm_auth.c | 6 +- source3/utils/smbcquotas.c | 3 +- source3/utils/wscript_build | 3 +- source3/wscript_build | 5 +- source4/dsdb/samdb/cracknames.c | 8 +- source4/dsdb/samdb/ldb_modules/acl_read.c | 331 ++++++- source4/dsdb/tests/python/acl.py | 68 ++ source4/dsdb/tests/python/confidential_attr.py | 1016 ++++++++++++++++++++ source4/dsdb/tests/python/ldap.py | 9 + source4/selftest/tests.py | 6 + source4/torture/basic/delete.c | 87 ++ source4/torture/drs/python/cracknames.py | 38 + 58 files changed, 4085 insertions(+), 652 deletions(-) copy lib/ldb/ABI/{ldb-1.4.1.sigs => ldb-1.4.2.sigs} (100%) copy lib/ldb/ABI/{pyldb-util.py3-1.4.1.sigs => pyldb-util-1.4.2.sigs} (100%) copy lib/ldb/ABI/{pyldb-util.py3-1.4.1.sigs => pyldb-util.py3-1.4.2.sigs} (100%) create mode 100644 libcli/auth/tests/ntlm_check.c create mode 100644 librpc/idl/quota.idl create mode 100644 python/samba/tests/dns_invalid.py create mode 100755 source3/script/tests/getset_quota.py create mode 100755 source3/script/tests/test_smbcquota.py copy python/samba/tests/policy.py => source3/script/tests/test_smbcquota.sh (52%) mode change 100644 => 100755 create mode 100755 source4/dsdb/tests/python/confidential_attr.py Changeset truncated at 500 lines: diff --git a/VERSION b/VERSION index 7da5b10..3bb84e7 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=2 +SAMBA_VERSION_RC_RELEASE=3 ######################################################## # To mark SVN snapshots this should be set to 'yes' # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index b28cbf4..97cd50b 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,7 +1,7 @@ Release Announcements ===================== -This is the second release candidate of Samba 4.9. This is *not* +This is the third release candidate of Samba 4.9. This is *not* intended for production environments and is designed for testing purposes only. Please report any defects via the Samba bug reporting system at https://bugzilla.samba.org/. @@ -451,6 +451,65 @@ Any external VFS modules will need to be updated to match these changes in order to work with 4.9.x. +CHANGES SINCE 4.9.0rc2 +====================== + +o Jeremy Allison <j...@samba.org> + * BUG 13453: CVE-2018-10858: libsmb: Harden smbc_readdir_internal() against + returns from malicious servers. + +o Andrew Bartlett <abart...@samba.org> + * BUG 13374: CVE-2018-1140: ldbsearch '(distinguishedName=abc)' and DNS query + with escapes crashes, ldb: Release LDB 1.3.5 for CVE-2018-1140 + * BUG 13552: CVE-2018-10918: cracknames: Fix DoS (NULL pointer de-ref) when + not servicePrincipalName is set on a user. + +o Tim Beale <timbe...@catalyst.net.nz> + * BUG 13434: CVE-2018-10919: acl_read: Fix unauthorized attribute access via + searches. + +o Samuel Cabrero <scabr...@suse.de> + * BUG 13540: ctdb_mutex_ceph_rados_helper: Set SIGINT signal handler. + +o Günther Deschner <g...@samba.org> + * BUG 13360: CVE-2018-1139 libcli/auth: Do not allow ntlmv1 over SMB1 when it + is disabled via "ntlm auth". + * BUG 13529: s3-tldap: do not install test_tldap. + +o David Disseldorp <dd...@samba.org> + * BUG 13540: ctdb_mutex_ceph_rados_helper: Fix deadlock via lock renewals. + +o Andrej Gessel <andrej.ges...@janztec.com> + * BUG 13374: CVE-2018-1140 Add NULL check for ldb_dn_get_casefold() in + ltdb_index_dn_attr(). + +o Amitay Isaacs <ami...@gmail.com> + * BUG 13554: ctdb-eventd: Fix CID 1438155. + +o Volker Lendecke <v...@samba.org> + * BUG 13553: Fix CIDs 1438243, (Unchecked return value) 1438244 + (Unsigned compared against 0), 1438245 (Dereference before null check) and + 1438246 (Unchecked return value). + * BUG 13554: ctdb: Fix a cut&paste error. + +o Oleksandr Natalenko <oleksa...@redhat.com> + * BUG 13559: systemd: Only start smb when network interfaces are up. + +o Noel Power <noel.po...@suse.com> + * BUG 13553: Fix quotas don't work with SMB2. + * BUG 13563: s3/smbd: Ensure quota code is only called when quota support + detected. + +o Anoop C S <anoo...@redhat.com> + * BUG 13204: s3/libsmb: Explicitly set delete_on_close token for rmdir. + +o Andreas Schneider <a...@samba.org> + * BUG 13561: s3:waf: Install eventlogadm to /usr/sbin. + +o Justin Stephenson <jstep...@redhat.com> + * BUG 13562: Shorten description in vfs_linux_xfs_sgid manual. + + CHANGES SINCE 4.9.0rc1 ====================== diff --git a/ctdb/common/path.c b/ctdb/common/path.c index 36706e4..1656646 100644 --- a/ctdb/common/path.c +++ b/ctdb/common/path.c @@ -149,7 +149,7 @@ const char *path_vardir(void) { bool ok; - if (! ctdb_paths.rundir_set) { + if (! ctdb_paths.vardir_set) { ok = path_construct(ctdb_paths.vardir, "var"); if (!ok) { D_ERR("Failed to construct VARDIR\n"); diff --git a/ctdb/event/event_tool.c b/ctdb/event/event_tool.c index 4768c67..f18deb8 100644 --- a/ctdb/event/event_tool.c +++ b/ctdb/event/event_tool.c @@ -320,7 +320,7 @@ static int event_command_script_list(TALLOC_CTX *mem_ctx, subdir = talloc_asprintf(mem_ctx, "events/%s", argv[0]); if (subdir == NULL) { - ret = ENOMEM; + return ENOMEM; } data_dir = path_datadir_append(mem_ctx, subdir); diff --git a/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c b/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c index 326a0b0..7ef76c2 100644 --- a/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c +++ b/ctdb/utils/ceph/ctdb_mutex_ceph_rados_helper.c @@ -1,7 +1,7 @@ /* CTDB mutex helper using Ceph librados locks - Copyright (C) David Disseldorp 2016 + Copyright (C) David Disseldorp 2016-2018 Based on ctdb_mutex_fcntl_helper.c, which is: Copyright (C) Martin Schwenke 2015 @@ -29,6 +29,11 @@ #define CTDB_MUTEX_CEPH_LOCK_NAME "ctdb_reclock_mutex" #define CTDB_MUTEX_CEPH_LOCK_COOKIE CTDB_MUTEX_CEPH_LOCK_NAME #define CTDB_MUTEX_CEPH_LOCK_DESC "CTDB recovery lock" +/* + * During failover it may take up to <lock duration> seconds before the + * newly elected recovery master can obtain the lock. + */ +#define CTDB_MUTEX_CEPH_LOCK_DURATION_SECS_DEFAULT 10 #define CTDB_MUTEX_STATUS_HOLDING "0" #define CTDB_MUTEX_STATUS_CONTENDED "1" @@ -88,24 +93,20 @@ static int ctdb_mutex_rados_ctx_create(const char *ceph_cluster_name, return 0; } -static void ctdb_mutex_rados_ctx_destroy(rados_t ceph_cluster, - rados_ioctx_t ioctx) -{ - rados_ioctx_destroy(ioctx); - rados_shutdown(ceph_cluster); -} - static int ctdb_mutex_rados_lock(rados_ioctx_t *ioctx, - const char *oid) + const char *oid, + uint64_t lock_duration_s, + uint8_t flags) { int ret; + struct timeval tv = { lock_duration_s, 0 }; ret = rados_lock_exclusive(ioctx, oid, - CTDB_MUTEX_CEPH_LOCK_NAME, + CTDB_MUTEX_CEPH_LOCK_NAME, CTDB_MUTEX_CEPH_LOCK_COOKIE, CTDB_MUTEX_CEPH_LOCK_DESC, - NULL, /* infinite duration */ - 0); + lock_duration_s == 0 ? NULL : &tv, + flags); if ((ret == -EEXIST) || (ret == -EBUSY)) { /* lock contention */ return ret; @@ -145,10 +146,13 @@ struct ctdb_mutex_rados_state { const char *ceph_auth_name; const char *pool_name; const char *object; + uint64_t lock_duration_s; int ppid; struct tevent_context *ev; - struct tevent_signal *sig_ev; - struct tevent_timer *timer_ev; + struct tevent_signal *sigterm_ev; + struct tevent_signal *sigint_ev; + struct tevent_timer *ppid_timer_ev; + struct tevent_timer *renew_timer_ev; rados_t ceph_cluster; rados_ioctx_t ioctx; }; @@ -161,29 +165,24 @@ static void ctdb_mutex_rados_sigterm_cb(struct tevent_context *ev, void *private_data) { struct ctdb_mutex_rados_state *cmr_state = private_data; - int ret; + int ret = 0; if (!cmr_state->holding_mutex) { fprintf(stderr, "Sigterm callback invoked without mutex!\n"); ret = -EINVAL; - goto err_ctx_cleanup; } - ret = ctdb_mutex_rados_unlock(cmr_state->ioctx, cmr_state->object); -err_ctx_cleanup: - ctdb_mutex_rados_ctx_destroy(cmr_state->ceph_cluster, - cmr_state->ioctx); talloc_free(cmr_state); exit(ret ? 1 : 0); } -static void ctdb_mutex_rados_timer_cb(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval current_time, - void *private_data) +static void ctdb_mutex_rados_ppid_timer_cb(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) { struct ctdb_mutex_rados_state *cmr_state = private_data; - int ret; + int ret = 0; if (!cmr_state->holding_mutex) { fprintf(stderr, "Timer callback invoked without mutex!\n"); @@ -193,26 +192,81 @@ static void ctdb_mutex_rados_timer_cb(struct tevent_context *ev, if ((kill(cmr_state->ppid, 0) == 0) || (errno != ESRCH)) { /* parent still around, keep waiting */ - cmr_state->timer_ev = tevent_add_timer(cmr_state->ev, cmr_state, + cmr_state->ppid_timer_ev = tevent_add_timer(cmr_state->ev, + cmr_state, tevent_timeval_current_ofs(5, 0), - ctdb_mutex_rados_timer_cb, - cmr_state); - if (cmr_state->timer_ev == NULL) { + ctdb_mutex_rados_ppid_timer_cb, + cmr_state); + if (cmr_state->ppid_timer_ev == NULL) { fprintf(stderr, "Failed to create timer event\n"); /* rely on signal cb */ } return; } - /* parent ended, drop lock and exit */ - ret = ctdb_mutex_rados_unlock(cmr_state->ioctx, cmr_state->object); + /* parent ended, drop lock (via destructor) and exit */ err_ctx_cleanup: - ctdb_mutex_rados_ctx_destroy(cmr_state->ceph_cluster, - cmr_state->ioctx); talloc_free(cmr_state); exit(ret ? 1 : 0); } +#define USECS_IN_SEC 1000000 + +static void ctdb_mutex_rados_lock_renew_timer_cb(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + struct ctdb_mutex_rados_state *cmr_state = private_data; + struct timeval tv; + int ret; + + ret = ctdb_mutex_rados_lock(cmr_state->ioctx, cmr_state->object, + cmr_state->lock_duration_s, + LIBRADOS_LOCK_FLAG_RENEW); + if (ret == -EBUSY) { + /* should never get -EEXIST on renewal */ + fprintf(stderr, "Lock contention during renew: %d\n", ret); + goto err_ctx_cleanup; + } else if (ret < 0) { + fprintf(stderr, "Lock renew failed\n"); + goto err_ctx_cleanup; + } + + tv = tevent_timeval_current_ofs(0, + cmr_state->lock_duration_s * (USECS_IN_SEC / 2)); + cmr_state->renew_timer_ev = tevent_add_timer(cmr_state->ev, + cmr_state, + tv, + ctdb_mutex_rados_lock_renew_timer_cb, + cmr_state); + if (cmr_state->renew_timer_ev == NULL) { + fprintf(stderr, "Failed to create timer event\n"); + goto err_ctx_cleanup; + } + + return; + +err_ctx_cleanup: + /* drop lock (via destructor) and exit */ + talloc_free(cmr_state); + exit(1); +} + +static int ctdb_mutex_rados_state_destroy(struct ctdb_mutex_rados_state *cmr_state) +{ + if (cmr_state->holding_mutex) { + ctdb_mutex_rados_unlock(cmr_state->ioctx, cmr_state->object); + } + if (cmr_state->ioctx != NULL) { + rados_ioctx_destroy(cmr_state->ioctx); + } + if (cmr_state->ceph_cluster != NULL) { + rados_shutdown(cmr_state->ceph_cluster); + } + return 0; +} + int main(int argc, char *argv[]) { int ret; @@ -220,9 +274,10 @@ int main(int argc, char *argv[]) progname = argv[0]; - if (argc != 5) { + if ((argc != 5) && (argc != 6)) { fprintf(stderr, "Usage: %s <Ceph Cluster> <Ceph user> " - "<RADOS pool> <RADOS object>\n", + "<RADOS pool> <RADOS object> " + "[lock duration secs]\n", progname); ret = -EINVAL; goto err_out; @@ -240,10 +295,24 @@ int main(int argc, char *argv[]) goto err_out; } + talloc_set_destructor(cmr_state, ctdb_mutex_rados_state_destroy); cmr_state->ceph_cluster_name = argv[1]; cmr_state->ceph_auth_name = argv[2]; cmr_state->pool_name = argv[3]; cmr_state->object = argv[4]; + if (argc == 6) { + /* optional lock duration provided */ + char *endptr = NULL; + cmr_state->lock_duration_s = strtoull(argv[5], &endptr, 0); + if ((endptr == argv[5]) || (*endptr != '\0')) { + fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); + ret = -EINVAL; + goto err_ctx_cleanup; + } + } else { + cmr_state->lock_duration_s + = CTDB_MUTEX_CEPH_LOCK_DURATION_SECS_DEFAULT; + } cmr_state->ppid = getppid(); if (cmr_state->ppid == 1) { @@ -257,7 +326,7 @@ int main(int argc, char *argv[]) */ fprintf(stderr, "%s: PPID == 1\n", progname); ret = -EPIPE; - goto err_state_free; + goto err_ctx_cleanup; } cmr_state->ev = tevent_context_init(cmr_state); @@ -265,30 +334,40 @@ int main(int argc, char *argv[]) fprintf(stderr, "tevent_context_init failed\n"); fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; - goto err_state_free; + goto err_ctx_cleanup; } /* wait for sigterm */ - cmr_state->sig_ev = tevent_add_signal(cmr_state->ev, cmr_state, SIGTERM, 0, + cmr_state->sigterm_ev = tevent_add_signal(cmr_state->ev, cmr_state, SIGTERM, 0, ctdb_mutex_rados_sigterm_cb, cmr_state); - if (cmr_state->sig_ev == NULL) { - fprintf(stderr, "Failed to create signal event\n"); + if (cmr_state->sigterm_ev == NULL) { + fprintf(stderr, "Failed to create term signal event\n"); fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; - goto err_state_free; + goto err_ctx_cleanup; + } + + cmr_state->sigint_ev = tevent_add_signal(cmr_state->ev, cmr_state, SIGINT, 0, + ctdb_mutex_rados_sigterm_cb, + cmr_state); + if (cmr_state->sigint_ev == NULL) { + fprintf(stderr, "Failed to create int signal event\n"); + fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); + ret = -ENOMEM; + goto err_ctx_cleanup; } /* periodically check parent */ - cmr_state->timer_ev = tevent_add_timer(cmr_state->ev, cmr_state, + cmr_state->ppid_timer_ev = tevent_add_timer(cmr_state->ev, cmr_state, tevent_timeval_current_ofs(5, 0), - ctdb_mutex_rados_timer_cb, + ctdb_mutex_rados_ppid_timer_cb, cmr_state); - if (cmr_state->timer_ev == NULL) { + if (cmr_state->ppid_timer_ev == NULL) { fprintf(stderr, "Failed to create timer event\n"); fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; - goto err_state_free; + goto err_ctx_cleanup; } ret = ctdb_mutex_rados_ctx_create(cmr_state->ceph_cluster_name, @@ -298,10 +377,12 @@ int main(int argc, char *argv[]) &cmr_state->ioctx); if (ret < 0) { fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); - goto err_state_free; + goto err_ctx_cleanup; } - ret = ctdb_mutex_rados_lock(cmr_state->ioctx, cmr_state->object); + ret = ctdb_mutex_rados_lock(cmr_state->ioctx, cmr_state->object, + cmr_state->lock_duration_s, + 0); if ((ret == -EEXIST) || (ret == -EBUSY)) { fprintf(stdout, CTDB_MUTEX_STATUS_CONTENDED); goto err_ctx_cleanup; @@ -309,8 +390,28 @@ int main(int argc, char *argv[]) fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); goto err_ctx_cleanup; } - cmr_state->holding_mutex = true; + + if (cmr_state->lock_duration_s != 0) { + /* + * renew (reobtain) the lock, using a period of half the lock + * duration. Convert to usecs to avoid rounding. + */ + struct timeval tv = tevent_timeval_current_ofs(0, + cmr_state->lock_duration_s * (USECS_IN_SEC / 2)); + cmr_state->renew_timer_ev = tevent_add_timer(cmr_state->ev, + cmr_state, + tv, + ctdb_mutex_rados_lock_renew_timer_cb, + cmr_state); + if (cmr_state->renew_timer_ev == NULL) { + fprintf(stderr, "Failed to create timer event\n"); + fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); + ret = -ENOMEM; + goto err_ctx_cleanup; + } + } + fprintf(stdout, CTDB_MUTEX_STATUS_HOLDING); /* wait for the signal / timer events to do their work */ @@ -319,9 +420,6 @@ int main(int argc, char *argv[]) goto err_ctx_cleanup; } err_ctx_cleanup: - ctdb_mutex_rados_ctx_destroy(cmr_state->ceph_cluster, - cmr_state->ioctx); -err_state_free: talloc_free(cmr_state); err_out: return ret ? 1 : 0; diff --git a/ctdb/utils/ceph/test_ceph_rados_reclock.sh b/ctdb/utils/ceph/test_ceph_rados_reclock.sh index 1adacf6..68b44ff 100755 --- a/ctdb/utils/ceph/test_ceph_rados_reclock.sh +++ b/ctdb/utils/ceph/test_ceph_rados_reclock.sh @@ -46,7 +46,9 @@ which ctdb_mutex_ceph_rados_helper || exit 1 TMP_DIR="$(mktemp --directory)" || exit 1 rados -p "$POOL" rm "$OBJECT" -(ctdb_mutex_ceph_rados_helper "$CLUSTER" "$USER" "$POOL" "$OBJECT" \ +# explicitly disable lock expiry (duration=0), to ensure that we don't get +# intermittent failures (due to renewal) from the lock state diff further down +(ctdb_mutex_ceph_rados_helper "$CLUSTER" "$USER" "$POOL" "$OBJECT" 0 \ > ${TMP_DIR}/first) & locker_pid=$! @@ -78,6 +80,9 @@ LOCKER_COOKIE="$(jq -r '.lockers[0].cookie' ${TMP_DIR}/lock_state_first)" LOCKER_DESC="$(jq -r '.lockers[0].description' ${TMP_DIR}/lock_state_first)" [ "$LOCKER_DESC" == "CTDB recovery lock" ] \ || _fail "unexpected locker description: $LOCKER_DESC" +LOCKER_EXP="$(jq -r '.lockers[0].expiration' ${TMP_DIR}/lock_state_first)" +[ "$LOCKER_EXP" == "0.000000" ] \ + || _fail "unexpected locker expiration: $LOCKER_EXP" # second attempt while first is still holding the lock - expect failure ctdb_mutex_ceph_rados_helper "$CLUSTER" "$USER" "$POOL" "$OBJECT" \ @@ -145,6 +150,56 @@ third_out=$(cat ${TMP_DIR}/third) [ "$third_out" == "0" ] \ || _fail "expected lock acquisition (0), but got $third_out" +# test renew / expire behaviour using a 1s expiry (update period = 500ms) +exec >${TMP_DIR}/forth -- ctdb_mutex_ceph_rados_helper "$CLUSTER" "$USER" \ -- Samba Shared Repository