Interesting issue with NDR_NOALIGN and nbt encoding.

Jeremy Allison jra at samba.org
Wed May 23 23:32:30 MDT 2012


On Thu, May 24, 2012 at 03:23:36PM +1000, Andrew Bartlett wrote:
> 
> That commit was in 2008, when we first got the WSPP docs, and I started
> to properly handle these structures.  I may not have filed a
> release-critical bug to move the comment, but I assure you, the rest of
> this code is very old indeed. 
> 
> What is much more relevant is the work I did (including testing) on
> WinXP failing to join 3.6 RC:
> https://bugzilla.samba.org/show_bug.cgi?id=8326
> 
> Also for background see the change Volker made in commit
> 2642f385887fbd3aecd4286a4d6223a21d981714
> Author: Volker Lendecke <vl at samba.org>
> Date:   Thu Nov 17 22:36:22 2011 +0100
> 
>     s3: Fix bug 8371
>     
>     ndr_set_flag or's in the given flag (ALIGN4). At this point,
> ndr->flags
>     contains NOALIGN, which will persist. In ndr_push_DATA_BLOB NOALIGN
> overrides
>     everything else, so that the ALIGN4 is not respected.
>     
>     Autobuild-User: Volker Lendecke <vlendec at samba.org>
>     Autobuild-Date: Fri Nov 18 09:33:37 CET 2011 on sn-devel-104
> 
> Metze: 
> The patch from metze on the bug
> https://bugzilla.samba.org/show_bug.cgi?id=8371
> https://attachments.samba.org/attachment.cgi?id=7118 does not seem to
> have made it into master, but also seems relevant. 

No worries - I wasn't blaming you, just trying
to understand the history of the code here. It's
really interesting stuff and you seemed to be the
last one touching it - and you know how that looks :-).

> I doubt it will allow us not to hand-generate to code you originally
> mentioned.  Certainly for the response 'netlogon'
>  packets, the issue is that the only way to parse them is to first read
> the last bytes, and then work forward. 

Can you explain more there ? Why is this the case ?

> > So attached is a patch to do just that. I'm testing
> > it currently in master, but I'd really like to get
> > feedback if I've missed something as to why it is
> > allowed to set any of LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8
> > concurrently with LIBNDR_FLAG_NOALIGN.
> 
> What is the point of LIBNDR_FLAG_NOALIGN then if all the alignment flags
> override it?

Ah - they're *SUPPOSED* to override it - that's the point.
But they do so temporarily.

Whenever you set a [flag(NDR_ALIGNXXX)] on a field
you're saying that field (and everything it contains)
need to be aligned on that boundary. But it's only
for that field.

So the code generated looks like :

	uint32_t _flags_save_xxx = ndr->flags;
	ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGNY);
	NDR_CHECK(ndr_push_XXX(ndr, NDR_SCALARS, r->xxx));
	ndr->flags = _flags_save_xxx;

Note we save off the containing ndr->flags and restore
after dealing with the sub-field.

So I think the correct fix here is to treat NDR_NOALIGN
in *exactly* the same way as the other NDR_ALIGNX types,
and when any of them is set it overrides any of the others
previously set.

I think the small patch I just posted (and am attaching
again to this email) does just that.

> I'm not totally sure here either, except to say that we need more
> known-correct blobs and tests for them, and that a good number of us
> have been stumbling though different parts of this puzzle over the past
> year, and at least we should connect the dots.  It may be that some of
> the top level NOALIGN flags are simply wrong. 

More testing gratefully received :-). I'm going to see
what feedback my change gets from the testers of that
3.6.x bug.

Jeremy.
-------------- next part --------------
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 37a3145..9e51fd9 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -135,7 +135,7 @@ struct ndr_print {
 #define LIBNDR_FLAG_ALIGN4       (1<<23)
 #define LIBNDR_FLAG_ALIGN8       (1<<24)
 
-#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8)
+#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_NOALIGN|LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8)
 
 #define LIBNDR_PRINT_ARRAY_HEX   (1<<25)
 #define LIBNDR_PRINT_SET_VALUES  (1<<26)
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index 2279d1c..3b83b65 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -383,6 +383,10 @@ _PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
 	}
 	if (new_flags & LIBNDR_ALIGN_FLAGS) {
 		(*pflags) &= ~LIBNDR_FLAG_REMAINING;
+		/* Ensure we only have the align
+		   flag set in the new_flags, remove
+		   any old align flag. */
+		(*pflags) &= ~LIBNDR_ALIGN_FLAGS;
 	}
 	if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
 		(*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;


More information about the samba-technical mailing list