Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GNOME
libsecret
Commits
b1b54f52
Commit
b1b54f52
authored
Sep 25, 2011
by
Stef Walter
Committed by
Stef Walter
Sep 25, 2011
Browse files
More Implementation of GSecretService session related code.
parent
3dfd7aa7
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
b1b54f52
...
...
@@ -22,5 +22,8 @@ Makefile.in
Makefile.in.in
missing
stamp*
.settings
.project
.cproject
/po/POTFILES
Makefile.decl
View file @
b1b54f52
NULL
=
autogen.sh
View file @
b1b54f52
...
...
@@ -8,7 +8,7 @@ ORIGDIR=`pwd`
cd
$srcdir
PROJECT
=
gsecret
TEST_TYPE
=
-f
FILE
=
library/gsecret-
data
.c
FILE
=
library/gsecret-
value
.c
DIE
=
0
...
...
configure.ac
View file @
b1b54f52
...
...
@@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_INIT([gsecret],[0.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=gsecret])
AC_CONFIG_SRCDIR([library/gsecret-
data
.c])
AC_CONFIG_SRCDIR([library/gsecret-
value
.c])
AC_CONFIG_HEADERS([config.h])
dnl Other initialization
...
...
@@ -70,10 +70,12 @@ fi
dnl *****************************
dnl *** done ***
dnl *****************************
AC_CONFIG_FILES([Makefile
egg/Makefile
po/Makefile.in
po/Makefile
library/Makefile
])
AC_CONFIG_FILES([
Makefile
egg/Makefile
po/Makefile.in
po/Makefile
library/Makefile
library/tests/Makefile
])
AC_OUTPUT
egg/Makefile.am
View file @
b1b54f52
...
...
@@ -6,5 +6,7 @@ INCLUDES = \
-I
$(top_srcdir)
libegg_la_SOURCES
=
\
egg-dh.c egg-dh.h
\
egg-hkdf.c egg-hkdf.h
\
egg-secure-memory.c egg-secure-memory.h
\
$(BUILT_SOURCES)
egg/egg-dh.c
0 → 100644
View file @
b1b54f52
This diff is collapsed.
Click to expand it.
egg/egg-dh.h
0 → 100644
View file @
b1b54f52
/*
* gnome-keyring
*
* Copyright (C) 2009 Stefan Walter
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef EGG_DH_H_
#define EGG_DH_H_
#include
<glib.h>
#include
<gcrypt.h>
gboolean
egg_dh_default_params
(
const
gchar
*
name
,
gcry_mpi_t
*
prime
,
gcry_mpi_t
*
base
);
gboolean
egg_dh_default_params_raw
(
const
gchar
*
name
,
gconstpointer
*
prime
,
gsize
*
n_prime
,
gconstpointer
*
base
,
gsize
*
n_base
);
gboolean
egg_dh_gen_pair
(
gcry_mpi_t
prime
,
gcry_mpi_t
base
,
guint
bits
,
gcry_mpi_t
*
pub
,
gcry_mpi_t
*
priv
);
gpointer
egg_dh_gen_secret
(
gcry_mpi_t
peer
,
gcry_mpi_t
priv
,
gcry_mpi_t
prime
,
gsize
*
bytes
);
#endif
/* EGG_DH_H_ */
egg/egg-hkdf.c
0 → 100644
View file @
b1b54f52
/*
* gnome-keyring
*
* Copyright (C) 2011 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Stef Walter <stefw@collabora.co.uk>
*/
#include
"config.h"
#include
"egg-hkdf.h"
#include
"egg-secure-memory.h"
#include
<gcrypt.h>
#include
<string.h>
gboolean
egg_hkdf_perform
(
const
gchar
*
hash_algo
,
gconstpointer
input
,
gsize
n_input
,
gconstpointer
salt
,
gsize
n_salt
,
gconstpointer
info
,
gsize
n_info
,
gpointer
output
,
gsize
n_output
)
{
gpointer
alloc
=
NULL
;
gpointer
buffer
=
NULL
;
gcry_md_hd_t
md1
,
md2
;
guint
hash_len
;
guchar
i
;
gint
flags
,
algo
;
gsize
step
,
n_buffer
;
guchar
*
at
;
gcry_error_t
gcry
;
algo
=
gcry_md_map_name
(
hash_algo
);
g_return_val_if_fail
(
algo
!=
0
,
FALSE
);
hash_len
=
gcry_md_get_algo_dlen
(
algo
);
g_return_val_if_fail
(
hash_len
!=
0
,
FALSE
);
g_return_val_if_fail
(
n_output
<=
255
*
hash_len
,
FALSE
);
/* Buffer we need to for intermediate stuff */
if
(
gcry_is_secure
(
input
))
{
flags
=
GCRY_MD_FLAG_SECURE
;
buffer
=
gcry_malloc_secure
(
hash_len
);
}
else
{
flags
=
0
;
buffer
=
gcry_malloc
(
hash_len
);
}
g_return_val_if_fail
(
buffer
,
FALSE
);
n_buffer
=
0
;
/* Salt defaults to hash_len zeros */
if
(
!
salt
)
{
salt
=
alloc
=
g_malloc0
(
hash_len
);
n_salt
=
hash_len
;
}
/* Step 1: Extract */
gcry
=
gcry_md_open
(
&
md1
,
algo
,
GCRY_MD_FLAG_HMAC
|
flags
);
g_return_val_if_fail
(
gcry
==
0
,
FALSE
);
gcry
=
gcry_md_setkey
(
md1
,
salt
,
n_salt
);
g_return_val_if_fail
(
gcry
==
0
,
FALSE
);
gcry_md_write
(
md1
,
input
,
n_input
);
/* Step 2: Expand */
gcry
=
gcry_md_open
(
&
md2
,
algo
,
GCRY_MD_FLAG_HMAC
|
flags
);
g_return_val_if_fail
(
gcry
==
0
,
FALSE
);
gcry
=
gcry_md_setkey
(
md2
,
gcry_md_read
(
md1
,
algo
),
hash_len
);
g_return_val_if_fail
(
gcry
==
0
,
FALSE
);
gcry_md_close
(
md1
);
at
=
output
;
for
(
i
=
1
;
i
<
256
;
++
i
)
{
gcry_md_reset
(
md2
);
gcry_md_write
(
md2
,
buffer
,
n_buffer
);
gcry_md_write
(
md2
,
info
,
n_info
);
gcry_md_write
(
md2
,
&
i
,
1
);
n_buffer
=
hash_len
;
memcpy
(
buffer
,
gcry_md_read
(
md2
,
algo
),
n_buffer
);
step
=
MIN
(
n_buffer
,
n_output
);
memcpy
(
at
,
buffer
,
step
);
n_output
-=
step
;
at
+=
step
;
if
(
!
n_output
)
break
;
}
g_free
(
alloc
);
gcry_free
(
buffer
);
return
TRUE
;
}
egg/egg-hkdf.h
0 → 100644
View file @
b1b54f52
/*
* gnome-keyring
*
* Copyright (C) 2011 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Stef Walter <stefw@collabora.co.uk>
*/
#ifndef EGG_HKDF_H_
#define EGG_HKDF_H_
#include
<glib.h>
gboolean
egg_hkdf_perform
(
const
gchar
*
hash_algo
,
gconstpointer
input
,
gsize
n_input
,
gconstpointer
salt
,
gsize
n_salt
,
gconstpointer
info
,
gsize
n_info
,
gpointer
output
,
gsize
n_output
);
#endif
/* EGG_HKDF_H_ */
egg/egg-secure-memory.c
View file @
b1b54f52
...
...
@@ -97,20 +97,22 @@ typedef void* word_t;
typedef
struct
_Cell
{
word_t
*
words
;
/* Pointer to secure memory */
size_t
n_words
;
/* Amount of secure memory in words */
size_t
allocated
;
/* Amount actually requested by app, in bytes, 0 if unused */
struct
_Cell
*
next
;
/* Next in unused memory ring, or NULL if used */
struct
_Cell
*
prev
;
/* Previous in unused memory ring, or NULL if used */
size_t
requested
;
/* Amount actually requested by app, in bytes, 0 if unused */
const
char
*
tag
;
/* Tag which describes the allocation */
struct
_Cell
*
next
;
/* Next in memory ring */
struct
_Cell
*
prev
;
/* Previous in memory ring */
}
Cell
;
/*
* A block of secure memory. This structure is the header in that block.
*/
typedef
struct
_Block
{
word_t
*
words
;
/* Actual memory hangs off here */
size_t
n_words
;
/* Number of words in block */
size_t
used
;
/* Number of used allocations */
struct
_Cell
*
unused
;
/* Ring of unused allocations */
struct
_Block
*
next
;
/* Next block in list */
word_t
*
words
;
/* Actual memory hangs off here */
size_t
n_words
;
/* Number of words in block */
size_t
n_used
;
/* Number of used allocations */
struct
_Cell
*
used_cells
;
/* Ring of used allocations */
struct
_Cell
*
unused_cells
;
/* Ring of unused allocations */
struct
_Block
*
next
;
/* Next block in list */
}
Block
;
/* -----------------------------------------------------------------------------
...
...
@@ -263,6 +265,8 @@ pool_free (void* item)
unused_push
(
&
pool
->
unused
,
item
);
}
#ifndef G_DISABLE_ASSERT
static
int
pool_valid
(
void
*
item
)
{
...
...
@@ -282,6 +286,8 @@ pool_valid (void* item)
return
0
;
}
#endif
/* G_DISABLE_ASSERT */
/* -----------------------------------------------------------------------------
* SEC ALLOCATION
*
...
...
@@ -459,7 +465,9 @@ sec_neighbor_after (Block *block, Cell *cell)
}
static
void
*
sec_alloc
(
Block
*
block
,
size_t
length
)
sec_alloc
(
Block
*
block
,
const
char
*
tag
,
size_t
length
)
{
Cell
*
cell
,
*
other
;
size_t
n_words
;
...
...
@@ -467,8 +475,9 @@ sec_alloc (Block *block, size_t length)
ASSERT
(
block
);
ASSERT
(
length
);
ASSERT
(
tag
);
if
(
!
block
->
unused
)
if
(
!
block
->
unused
_cells
)
return
NULL
;
/*
...
...
@@ -482,10 +491,10 @@ sec_alloc (Block *block, size_t length)
n_words
=
sec_size_to_words
(
length
)
+
2
;
/* Look for a cell of at least our required size */
cell
=
block
->
unused
;
cell
=
block
->
unused
_cells
;
while
(
cell
->
n_words
<
n_words
)
{
cell
=
cell
->
next
;
if
(
cell
==
block
->
unused
)
{
if
(
cell
==
block
->
unused
_cells
)
{
cell
=
NULL
;
break
;
}
...
...
@@ -493,8 +502,9 @@ sec_alloc (Block *block, size_t length)
if
(
!
cell
)
return
NULL
;
ASSERT
(
cell
->
allocated
==
0
);
ASSERT
(
cell
->
tag
==
NULL
);
ASSERT
(
cell
->
requested
==
0
);
ASSERT
(
cell
->
prev
);
ASSERT
(
cell
->
words
);
sec_check_guards
(
cell
);
...
...
@@ -516,10 +526,12 @@ sec_alloc (Block *block, size_t length)
}
if
(
cell
->
next
)
sec_remove_cell_ring
(
&
block
->
unused
,
cell
);
++
block
->
used
;
cell
->
allocated
=
length
;
sec_remove_cell_ring
(
&
block
->
unused_cells
,
cell
);
++
block
->
n_used
;
cell
->
tag
=
tag
;
cell
->
requested
=
length
;
sec_insert_cell_ring
(
&
block
->
used_cells
,
cell
);
memory
=
sec_cell_to_memory
(
cell
);
#ifdef WITH_VALGRIND
...
...
@@ -555,16 +567,19 @@ sec_free (Block *block, void *memory)
#endif
sec_check_guards
(
cell
);
sec_clear_memory
(
memory
,
0
,
cell
->
alloca
ted
);
sec_clear_memory
(
memory
,
0
,
cell
->
reques
ted
);
sec_check_guards
(
cell
);
ASSERT
(
cell
->
next
==
NULL
);
ASSERT
(
cell
->
prev
==
NULL
);
ASSERT
(
cell
->
allocated
>
0
);
ASSERT
(
cell
->
requested
>
0
);
ASSERT
(
cell
->
tag
!=
NULL
);
/* Remove from the used cell ring */
sec_remove_cell_ring
(
&
block
->
used_cells
,
cell
);
/* Find previous unallocated neighbor, and merge if possible */
other
=
sec_neighbor_before
(
block
,
cell
);
if
(
other
&&
other
->
allocated
==
0
)
{
if
(
other
&&
other
->
requested
==
0
)
{
ASSERT
(
other
->
tag
==
NULL
);
ASSERT
(
other
->
next
&&
other
->
prev
);
other
->
n_words
+=
cell
->
n_words
;
sec_write_guards
(
other
);
...
...
@@ -574,12 +589,13 @@ sec_free (Block *block, void *memory)
/* Find next unallocated neighbor, and merge if possible */
other
=
sec_neighbor_after
(
block
,
cell
);
if
(
other
&&
other
->
allocated
==
0
)
{
if
(
other
&&
other
->
requested
==
0
)
{
ASSERT
(
other
->
tag
==
NULL
);
ASSERT
(
other
->
next
&&
other
->
prev
);
other
->
n_words
+=
cell
->
n_words
;
other
->
words
=
cell
->
words
;
if
(
cell
->
next
)
sec_remove_cell_ring
(
&
block
->
unused
,
cell
);
sec_remove_cell_ring
(
&
block
->
unused
_cells
,
cell
);
sec_write_guards
(
other
);
pool_free
(
cell
);
cell
=
other
;
...
...
@@ -587,25 +603,30 @@ sec_free (Block *block, void *memory)
/* Add to the unused list if not already there */
if
(
!
cell
->
next
)
sec_insert_cell_ring
(
&
block
->
unused
,
cell
);
cell
->
allocated
=
0
;
--
block
->
used
;
sec_insert_cell_ring
(
&
block
->
unused_cells
,
cell
);
cell
->
tag
=
NULL
;
cell
->
requested
=
0
;
--
block
->
n_used
;
return
NULL
;
}
static
void
*
sec_realloc
(
Block
*
block
,
void
*
memory
,
size_t
length
)
sec_realloc
(
Block
*
block
,
const
char
*
tag
,
void
*
memory
,
size_t
length
)
{
Cell
*
cell
,
*
other
;
word_t
*
word
;
size_t
n_words
;
size_t
valid
;
void
*
alloc
;
/* Standard realloc behavior, should have been handled elsewhere */
ASSERT
(
memory
!=
NULL
);
ASSERT
(
length
>
0
);
ASSERT
(
tag
!=
NULL
);
/* Dig out where the meta should be */
word
=
memory
;
...
...
@@ -621,13 +642,12 @@ sec_realloc (Block *block, void *memory, size_t length)
/* Validate that it's actually for real */
sec_check_guards
(
cell
);
ASSERT
(
cell
->
allocated
>
0
);
ASSERT
(
cell
->
next
==
NULL
);
ASSERT
(
cell
->
prev
==
NULL
);
ASSERT
(
cell
->
requested
>
0
);
ASSERT
(
cell
->
tag
!=
NULL
);
/* The amount of valid data */
valid
=
cell
->
alloca
ted
;
valid
=
cell
->
reques
ted
;
/* How many words we actually want */
n_words
=
sec_size_to_words
(
length
)
+
2
;
...
...
@@ -635,7 +655,7 @@ sec_realloc (Block *block, void *memory, size_t length)
if
(
n_words
<=
cell
->
n_words
)
{
/* TODO: No shrinking behavior yet */
cell
->
alloca
ted
=
length
;
cell
->
reques
ted
=
length
;
alloc
=
sec_cell_to_memory
(
cell
);
#ifdef WITH_VALGRIND
...
...
@@ -658,14 +678,14 @@ sec_realloc (Block *block, void *memory, size_t length)
/* See if we have a neighbor who can give us some memory */
other
=
sec_neighbor_after
(
block
,
cell
);
if
(
!
other
||
other
->
alloca
ted
!=
0
)
if
(
!
other
||
other
->
reques
ted
!=
0
)
break
;
/* Eat the whole neighbor if not too big */
if
(
n_words
-
cell
->
n_words
+
WASTE
>=
other
->
n_words
)
{
cell
->
n_words
+=
other
->
n_words
;
sec_write_guards
(
cell
);
sec_remove_cell_ring
(
&
block
->
unused
,
other
);
sec_remove_cell_ring
(
&
block
->
unused
_cells
,
other
);
pool_free
(
other
);
/* Steal from the neighbor */
...
...
@@ -679,18 +699,19 @@ sec_realloc (Block *block, void *memory, size_t length)
}
if
(
cell
->
n_words
>=
n_words
)
{
cell
->
allocated
=
length
;
cell
->
requested
=
length
;
cell
->
tag
=
tag
;
alloc
=
sec_cell_to_memory
(
cell
);
#ifdef WITH_VALGRIND
VALGRIND_MAKE_MEM_DEFINED
(
alloc
,
length
);
#endif
return
sec_clear_memory
(
alloc
,
valid
,
length
);
}
/* That didn't work, try alloc/free */
alloc
=
sec_alloc
(
block
,
length
);
alloc
=
sec_alloc
(
block
,
tag
,
length
);
if
(
alloc
)
{
memcpy
(
alloc
,
memory
,
valid
);
sec_free
(
block
,
memory
);
...
...
@@ -722,15 +743,14 @@ sec_allocated (Block *block, void *memory)
cell
=
*
word
;
sec_check_guards
(
cell
);
ASSERT
(
cell
->
next
==
NULL
);
ASSERT
(
cell
->
prev
==
NULL
);
ASSERT
(
cell
->
allocated
>
0
);
ASSERT
(
cell
->
requested
>
0
);
ASSERT
(
cell
->
tag
!=
NULL
);
#ifdef WITH_VALGRIND
VALGRIND_MAKE_MEM_NOACCESS
(
word
,
sizeof
(
word_t
));
#endif
return
cell
->
alloca
ted
;
return
cell
->
reques
ted
;
}
static
void
...
...
@@ -753,15 +773,19 @@ sec_validate (Block *block)
sec_check_guards
(
cell
);
/* Is it an allocated block? */
if
(
cell
->
allocated
>
0
)
{
ASSERT
(
cell
->
next
==
NULL
);
ASSERT
(
cell
->
prev
==
NULL
);
ASSERT
(
cell
->
allocated
<=
(
cell
->
n_words
-
2
)
*
sizeof
(
word_t
));
if
(
cell
->
requested
>
0
)
{
ASSERT
(
cell
->
tag
!=
NULL
);
ASSERT
(
cell
->
next
!=
NULL
);
ASSERT
(
cell
->
prev
!=
NULL
);
ASSERT
(
cell
->
next
->
prev
==
cell
);
ASSERT
(
cell
->
prev
->
next
==
cell
);
ASSERT
(
cell
->
requested
<=
(
cell
->
n_words
-
2
)
*
sizeof
(
word_t
));
/* An unused block */
}
else
{
ASSERT
(
cell
->
next
);
ASSERT
(
cell
->
prev
);
ASSERT
(
cell
->
tag
==
NULL
);
ASSERT
(
cell
->
next
!=
NULL
);
ASSERT
(
cell
->
prev
!=
NULL
);
ASSERT
(
cell
->
next
->
prev
==
cell
);
ASSERT
(
cell
->
prev
->
next
==
cell
);
}
...
...
@@ -777,13 +801,15 @@ sec_validate (Block *block)
*/
static
void
*
sec_acquire_pages
(
size_t
*
sz
)
sec_acquire_pages
(
size_t
*
sz
,
const
char
*
during_tag
)
{
void
*
pages
;
unsigned
long
pgsize
;
ASSERT
(
sz
);
ASSERT
(
*
sz
);
ASSERT
(
during_tag
);
/* Make sure sz is a multiple of the page size */
pgsize
=
getpagesize
();
...
...
@@ -793,16 +819,16 @@ sec_acquire_pages (size_t *sz)
pages
=
mmap
(
0
,
*
sz
,
PROT_READ
|
PROT_WRITE
,
MAP_PRIVATE
|
MAP_ANON
,
-
1
,
0
);
if
(
pages
==
MAP_FAILED
)
{
if
(
lock_warning
&&
egg_secure_warnings
)
fprintf
(
stderr
,
"couldn't map %lu bytes of
private
memory: %s
\n
"
,
(
unsigned
long
)
*
sz
,
strerror
(
errno
));
fprintf
(
stderr
,
"couldn't map %lu bytes of memory
(%s)
: %s
\n
"
,
(
unsigned
long
)
*
sz
,
during_tag
,
strerror
(
errno
));
lock_warning
=
0
;
return
NULL
;
}
if
(
mlock
(
pages
,
*
sz
)
<
0
)
{
if
(
lock_warning
&&
egg_secure_warnings
&&
errno
!=
EPERM
)
{
fprintf
(
stderr
,
"couldn't lock %lu bytes of
private
memory: %s
\n
"
,
(
unsigned
long
)
*
sz
,
strerror
(
errno
));
fprintf
(
stderr
,
"couldn't lock %lu bytes of memory
(%s)
: %s
\n
"
,
(
unsigned
long
)
*
sz
,
during_tag
,
strerror
(
errno
));
lock_warning
=
0
;
}
munmap
(
pages
,
*
sz
);
...
...
@@ -850,11 +876,14 @@ sec_release_pages (void *pages, size_t sz)
static
Block
*
all_blocks
=
NULL
;
static
Block
*
sec_block_create
(
size_t
size
)
sec_block_create
(
size_t
size
,
const
char
*
during_tag
)
{
Block
*
block
;
Cell
*
cell
;
ASSERT
(
during_tag
);
#if FORCE_FALLBACK_MEMORY
/* We can force all all memory to be malloced */
return
NULL
;
...
...
@@ -874,7 +903,7 @@ sec_block_create (size_t size)
if
(
size
<
DEFAULT_BLOCK_SIZE
)
size
=
DEFAULT_BLOCK_SIZE
;
block
->
words
=
sec_acquire_pages
(
&
size
);
block
->
words
=
sec_acquire_pages
(
&
size
,
during_tag
);
block
->
n_words
=
size
/
sizeof
(
word_t
);
if
(
!
block
->
words
)
{
pool_free
(
block
);
...
...
@@ -889,10 +918,10 @@ sec_block_create (size_t size)
/* The first cell to allocate from */
cell
->
words
=
block
->
words
;
cell
->
n_words
=
block
->
n_words
;
cell
->
alloca
ted
=
0
;
cell
->
reques
ted
=
0
;
sec_write_guards
(
cell
);
sec_insert_cell_ring
(
&
block
->
unused
,
cell
);