diff options
author | Jeremy Allison <jra@samba.org> | 2001-09-18 06:41:29 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-09-18 06:41:29 +0000 |
commit | 5bc82e443b2da885aa0a504906789c006b3cf17a (patch) | |
tree | 6440822892634cb6e10c373eeea833066ab37a96 /source3 | |
parent | 36a6611da2820da3635a8158dd26f41732b5b4fd (diff) | |
download | samba-5bc82e443b2da885aa0a504906789c006b3cf17a.tar.gz samba-5bc82e443b2da885aa0a504906789c006b3cf17a.tar.bz2 samba-5bc82e443b2da885aa0a504906789c006b3cf17a.zip |
Correct fix for unaligned memcpy - malloc'ed memory incremented by sizeof(struct locking_data)
was not forced to be 8 byte aligned. Use union to force it to be correctly aligned
for memcpy and use void *, to tell compiler not to optimize aligned copy (this last fix
suggested by Trond @ RedHat). The first fix should be sufficient, but this provides a
"belt and braces" fix.
Jeremy.
(This used to be commit 22c5915bb466529ac1bcb5c2574888b360a9775b)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/smb.h | 5 | ||||
-rw-r--r-- | source3/locking/locking.c | 38 |
2 files changed, 24 insertions, 19 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 85cd042976..abf13533d2 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -652,7 +652,10 @@ struct locking_key { }; struct locking_data { - int num_share_mode_entries; + union { + int num_share_mode_entries; + share_mode_entry dummy; /* Needed for alignment. */ + } u; /* the following two entries are implicit share_mode_entry modes[num_share_mode_entries]; char file_name[]; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index a942965684..23766f41dc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -231,7 +231,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - for (i=0;i<data->num_share_mode_entries;) { + for (i=0;i<data->u.num_share_mode_entries;) { if (check_self && (shares[i].pid == mypid)) { DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", @@ -245,7 +245,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat continue; } - data->num_share_mode_entries--; + data->u.num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; @@ -256,7 +256,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat dbuf.dsize -= del_count * sizeof(*shares); /* store it back in the database */ - if (data->num_share_mode_entries == 0) { + if (data->u.num_share_mode_entries == 0) { if (tdb_delete(ttdb, kbuf) == -1) ret = -1; } else { @@ -433,7 +433,7 @@ int get_share_modes(connection_struct *conn, return 0; data = (struct locking_data *)dbuf.dptr; - ret = data->num_share_mode_entries; + ret = data->u.num_share_mode_entries; if(ret) *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares)); SAFE_FREE(dbuf.dptr); @@ -451,12 +451,14 @@ int get_share_modes(connection_struct *conn, static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) { share_mode_entry *e = (share_mode_entry *)p; + void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + memset(e, '\0', sizeof(share_mode_entry)); e->pid = sys_getpid(); e->share_mode = fsp->share_mode; e->op_port = port; e->op_type = op_type; - e->time = fsp->open_time; + memcpy(x, &fsp->open_time, sizeof(struct timeval)); } /******************************************************************* @@ -504,13 +506,13 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, * from the record. */ - DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->num_share_mode_entries )); + DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->u.num_share_mode_entries )); - for (i=0;i<data->num_share_mode_entries;) { + for (i=0;i<data->u.num_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { if (ppse) *ppse = memdup(&shares[i], sizeof(*shares)); - data->num_share_mode_entries--; + data->u.num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; @@ -526,10 +528,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, /* the record may have shrunk a bit */ dbuf.dsize -= del_count * sizeof(*shares); - count = (ssize_t)data->num_share_mode_entries; + count = (ssize_t)data->u.num_share_mode_entries; /* store it back in the database */ - if (data->num_share_mode_entries == 0) { + if (data->u.num_share_mode_entries == 0) { if (tdb_delete(tdb, locking_key(dev, inode)) == -1) count = -1; } else { @@ -585,7 +587,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) if (!p) return False; data = (struct locking_data *)p; - data->num_share_mode_entries = 1; + data->u.num_share_mode_entries = 1; pstrcpy(p + sizeof(*data) + sizeof(share_mode_entry), fname); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; @@ -599,7 +601,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) /* we're adding to an existing entry - this is a bit fiddly */ data = (struct locking_data *)dbuf.dptr; - data->num_share_mode_entries++; + data->u.num_share_mode_entries++; size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); if (!p) @@ -640,7 +642,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* find any with our pid and call the supplied function */ - for (i=0;i<data->num_share_mode_entries;i++) { + for (i=0;i<data->u.num_share_mode_entries;i++) { if (share_modes_identical(entry, &shares[i])) { mod_fn(&shares[i], dev, inode, param); need_store=True; @@ -649,7 +651,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en /* if the mod fn was called then store it back */ if (need_store) { - if (data->num_share_mode_entries == 0) { + if (data->u.num_share_mode_entries == 0) { if (tdb_delete(tdb, locking_key(dev, inode)) == -1) need_store = False; } else { @@ -739,14 +741,14 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* Set/Unset the delete on close element. */ - for (i=0;i<data->num_share_mode_entries;i++,shares++) { + for (i=0;i<data->u.num_share_mode_entries;i++,shares++) { shares->share_mode = (delete_on_close ? (shares->share_mode | DELETE_ON_CLOSE_FLAG) : (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) ); } /* store it back */ - if (data->num_share_mode_entries) { + if (data->u.num_share_mode_entries) { if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) { SAFE_FREE(dbuf.dptr); return False; @@ -774,9 +776,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - name = dbuf.dptr + sizeof(*data) + data->num_share_mode_entries*sizeof(*shares); + name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares); - for (i=0;i<data->num_share_mode_entries;i++) { + for (i=0;i<data->u.num_share_mode_entries;i++) { traverse_callback(&shares[i], name); } return 0; |