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

Jeremy Allison jra at samba.org
Wed Nov 28 21:03:22 MST 2012


On Wed, Nov 28, 2012 at 07:54:08PM -0800, Richard Sharpe wrote:
> 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.

Thanks Richard, I'll look into this tomorrow (been sick all
day today, hopefully I'll be up to fixing this then).

Cheers,

	Jeremy.


More information about the samba-technical mailing list