A small problem with source3/locking.c:traverse_fn that causes a crash if a share_mode_lock contains a delete token

Richard Sharpe realrichardsharpe at gmail.com
Wed Nov 28 20:54:08 MST 2012


Hi folks,

Currently, the traverse_fn (which is used by smbstatus) does this to
try to deal with delete tokens:

        for (i = 0; i < data->u.s.num_delete_token_entries; i++) {
                uint32_t del_token_size;
                memcpy(&del_token_size, del_tokens, sizeof(uint32_t));
                total_del_token_size += del_token_size;
                del_tokens += del_token_size;
        }

It clearly thinks that there is a uint32_t length in front of each
such token. However, unparse_share_modes does this:

        /* Store any delete on close tokens. */
        for (pdtl = lck->delete_tokens; pdtl; pdtl = pdtl->next) {
                struct security_unix_token *pdt = pdtl->delete_token;
                struct security_token *pdt_nt = pdtl->delete_nt_token;
                uint8_t *p = result.dptr + offset;
                DATA_BLOB blob;
                enum ndr_err_code ndr_err;

                memcpy(p, &pdtl->name_hash, sizeof(uint32_t));
                p += sizeof(uint32_t);
                offset += sizeof(uint32_t);

So, it seems that the name hash should be in front of the token, and
this causes a crash if there is a token.

I thought that the following patch would fix things, but it crashes as well.

-bash-4.0$ diff -up locking.c.orig locking.c
--- locking.c.orig      2012-11-28 17:44:05.265719981 -0800
+++ locking.c   2012-11-28 19:37:04.378894979 -0800
@@ -1741,6 +1741,8 @@ static int traverse_fn(struct db_record
        const char *fname;
        const char *del_tokens;
        uint32_t total_del_token_size = 0;
+       struct share_mode_lock *lck = TALLOC_ZERO_P(talloc_tos(),
+                                               struct share_mode_lock);
        int i;

        /* Ensure this is a locking_key record. */
@@ -1752,6 +1754,13 @@ static int traverse_fn(struct db_record
        del_tokens = (const char *)rec->value.dptr + sizeof(*data) +
                data->u.s.num_share_mode_entries*sizeof(*shares);

+
+       if (data->u.s.num_delete_token_entries)
+               total_del_token_size = parse_delete_tokens_list(lck,
+                                               data,
+                                               rec->value);
+       TALLOC_FREE(lck);
+#if 0
        for (i = 0; i < data->u.s.num_delete_token_entries; i++) {
                uint32_t del_token_size;
                memcpy(&del_token_size, del_tokens, sizeof(uint32_t));
@@ -1759,6 +1768,8 @@ static int traverse_fn(struct db_record
                del_tokens += del_token_size;
        }

+#endif
+
        sharepath = (const char *)rec->value.dptr + sizeof(*data) +
                data->u.s.num_share_mode_entries*sizeof(*shares) +
                total_del_token_size;

The crash is:

../librpc/ndr/ndr_basic.c:830: uid_t pull doesn't fit 0x0000820284f2a1c1

Program received signal SIGSEGV, Segmentation fault.

-- 
Regards,
Richard Sharpe
(何以解憂?唯有杜康。--曹操)


More information about the samba-technical mailing list